From 7cd8f7cad3ab699540e945b4942ff22fa15f7000 Mon Sep 17 00:00:00 2001 From: Brandon Taylor Date: Wed, 19 Nov 2014 10:58:55 -0500 Subject: [PATCH 1/7] Added Python 3 compatibility to sample project. Removed utils file and moved map_path function to settings.py. Refactored tests for Python 2 and 3 compatibility. Added inheritance check to get proper determination if a SortableForeignKey field is defined but the specified model does not inherit from Sortable. --- adminsortable/utils.py | 22 ++- python3_sample_project/app/__init__.py | 0 python3_sample_project/app/admin.py | 84 --------- python3_sample_project/app/fixtures/data.json | 52 ------ .../app/migrations/0001_initial.py | 146 --------------- ...sortablecategory_sortablecategorywidget.py | 44 ----- .../0003_selfreferentialcategory.py | 28 --- .../app/migrations/0004_auto_20141029_1612.py | 24 --- .../app/migrations/__init__.py | 0 python3_sample_project/app/models.py | 169 ------------------ python3_sample_project/app/tests.py | 158 ---------------- .../database/python3-test-project.sqlite3 | Bin 84992 -> 0 bytes python3_sample_project/manage.py | 15 -- .../python3_sample_project/__init__.py | 0 .../python3_sample_project/settings.py | 99 ---------- .../python3_sample_project/urls.py | 10 -- .../python3_sample_project/utils.py | 6 - .../python3_sample_project/wsgi.py | 14 -- sample_project/app/admin.py | 4 +- sample_project/app/models.py | 38 ++-- sample_project/app/tests.py | 12 +- sample_project/database/test_project.sqlite | Bin 99328 -> 100352 bytes sample_project/sample_project/settings.py | 8 +- 23 files changed, 57 insertions(+), 876 deletions(-) delete mode 100644 python3_sample_project/app/__init__.py delete mode 100644 python3_sample_project/app/admin.py delete mode 100644 python3_sample_project/app/fixtures/data.json delete mode 100644 python3_sample_project/app/migrations/0001_initial.py delete mode 100644 python3_sample_project/app/migrations/0002_nonsortablecategory_sortablecategorywidget.py delete mode 100644 python3_sample_project/app/migrations/0003_selfreferentialcategory.py delete mode 100644 python3_sample_project/app/migrations/0004_auto_20141029_1612.py delete mode 100644 python3_sample_project/app/migrations/__init__.py delete mode 100644 python3_sample_project/app/models.py delete mode 100644 python3_sample_project/app/tests.py delete mode 100644 python3_sample_project/database/python3-test-project.sqlite3 delete mode 100644 python3_sample_project/manage.py delete mode 100644 python3_sample_project/python3_sample_project/__init__.py delete mode 100644 python3_sample_project/python3_sample_project/settings.py delete mode 100644 python3_sample_project/python3_sample_project/urls.py delete mode 100644 python3_sample_project/python3_sample_project/utils.py delete mode 100644 python3_sample_project/python3_sample_project/wsgi.py diff --git a/adminsortable/utils.py b/adminsortable/utils.py index 82141d9..85237bd 100644 --- a/adminsortable/utils.py +++ b/adminsortable/utils.py @@ -1,9 +1,13 @@ from .models import Sortable, SortableForeignKey +def check_inheritance(obj): + return issubclass(type(obj), Sortable) + + def get_is_sortable(objects): if objects: - if issubclass(type(objects[0]), Sortable): + if check_inheritance(objects[0]): if objects.count() > 1: return True return False @@ -11,7 +15,8 @@ def get_is_sortable(objects): def is_self_referential(cls): cls_type = type(cls) - sortable_subclass = issubclass(cls_type, Sortable) + sortable_subclass = check_inheritance(cls_type) + # sortable_subclass = issubclass(cls_type, Sortable) sortable_foreign_key_subclass = issubclass(cls_type, SortableForeignKey) if sortable_foreign_key_subclass and not sortable_subclass: return True @@ -20,11 +25,12 @@ def is_self_referential(cls): def check_model_is_sortable(cls): if cls: - if is_self_referential(cls): - objects = cls.model.objects - else: - objects = cls.objects + if check_inheritance(cls): + if is_self_referential(cls): + objects = cls.model.objects + else: + objects = cls.objects - if objects.count() > 1: - return True + if objects.count() > 1: + return True return False diff --git a/python3_sample_project/app/__init__.py b/python3_sample_project/app/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/python3_sample_project/app/admin.py b/python3_sample_project/app/admin.py deleted file mode 100644 index 580bf5a..0000000 --- a/python3_sample_project/app/admin.py +++ /dev/null @@ -1,84 +0,0 @@ -from django.contrib import admin - -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, - Component, Person, NonSortableCategory, SortableCategoryWidget, - SortableNonInlineCategory, SelfReferentialCategory) - - -admin.site.register(Category, SortableAdmin) - - -class ComponentInline(SortableStackedInline): - model = Component - - def queryset(self, request): - qs = super(ComponentInline, self).queryset( - request).exclude(title__icontains='2') - if get_is_sortable(qs): - self.model.is_sortable = True - else: - self.model.is_sortable = False - return qs - - -class WidgetAdmin(SortableAdmin): - def queryset(self, request): - """ - A simple example demonstrating that adminsortable works even in - situations where you need to filter the queryset in admin. Here, - we are just filtering out `widget` instances with an pk higher - than 3 - """ - qs = super(WidgetAdmin, self).queryset(request) - return qs.filter(id__lte=3) - - inlines = [ComponentInline] - -admin.site.register(Widget, WidgetAdmin) - - -class CreditInline(SortableTabularInline): - model = Credit - extra = 1 - - -class NoteInline(SortableStackedInline): - model = Note - extra = 0 - - -class GenericNoteInline(SortableGenericStackedInline): - model = GenericNote - extra = 0 - - -class ProjectAdmin(SortableAdmin): - inlines = [CreditInline, NoteInline, GenericNoteInline] - list_display = ['__str__', 'category'] - -admin.site.register(Project, ProjectAdmin) - - -class PersonAdmin(SortableAdmin): - list_display = ['__str__', 'is_board_member'] - -admin.site.register(Person, PersonAdmin) - - -class SortableCategoryWidgetInline(SortableStackedInline): - model = SortableCategoryWidget - extra = 0 - - -class NonSortableCategoryAdmin(NonSortableParentAdmin): - inlines = [SortableCategoryWidgetInline] - -admin.site.register(NonSortableCategory, NonSortableCategoryAdmin) - -admin.site.register(SortableNonInlineCategory, SortableAdmin) - -admin.site.register(SelfReferentialCategory, SortableAdmin) diff --git a/python3_sample_project/app/fixtures/data.json b/python3_sample_project/app/fixtures/data.json deleted file mode 100644 index 25f6d7d..0000000 --- a/python3_sample_project/app/fixtures/data.json +++ /dev/null @@ -1,52 +0,0 @@ -[ -{ - "fields": { - "is_board_member": true, - "order": 1, - "first_name": "Brandon", - "last_name": "Taylor" - }, - "pk": 1, - "model": "app.person" -}, -{ - "fields": { - "is_board_member": true, - "order": 2, - "first_name": "Kerri", - "last_name": "Taylor" - }, - "pk": 2, - "model": "app.person" -}, -{ - "fields": { - "is_board_member": false, - "order": 3, - "first_name": "Sarah", - "last_name": "Taylor" - }, - "pk": 3, - "model": "app.person" -}, -{ - "fields": { - "is_board_member": false, - "order": 4, - "first_name": "Renna", - "last_name": "Taylor" - }, - "pk": 4, - "model": "app.person" -}, -{ - "fields": { - "is_board_member": false, - "order": 5, - "first_name": "Jake", - "last_name": "Taylor" - }, - "pk": 5, - "model": "app.person" -} -] diff --git a/python3_sample_project/app/migrations/0001_initial.py b/python3_sample_project/app/migrations/0001_initial.py deleted file mode 100644 index ab0527a..0000000 --- a/python3_sample_project/app/migrations/0001_initial.py +++ /dev/null @@ -1,146 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import models, migrations -import adminsortable.fields - - -class Migration(migrations.Migration): - - dependencies = [ - ('contenttypes', '0001_initial'), - ] - - operations = [ - migrations.CreateModel( - name='Category', - fields=[ - ('id', models.AutoField(auto_created=True, serialize=False, primary_key=True, verbose_name='ID')), - ('order', models.PositiveIntegerField(editable=False, default=1, db_index=True)), - ('title', models.CharField(max_length=50)), - ], - options={ - 'ordering': ['order'], - 'verbose_name_plural': 'Categories', - 'abstract': False, - }, - bases=(models.Model,), - ), - migrations.CreateModel( - name='Component', - fields=[ - ('id', models.AutoField(auto_created=True, serialize=False, primary_key=True, verbose_name='ID')), - ('order', models.PositiveIntegerField(editable=False, default=1, db_index=True)), - ('title', models.CharField(max_length=50)), - ], - options={ - 'ordering': ['order'], - 'abstract': False, - }, - bases=(models.Model,), - ), - migrations.CreateModel( - name='Credit', - fields=[ - ('id', models.AutoField(auto_created=True, serialize=False, primary_key=True, verbose_name='ID')), - ('order', models.PositiveIntegerField(editable=False, default=1, db_index=True)), - ('first_name', models.CharField(max_length=30)), - ('last_name', models.CharField(max_length=30)), - ], - options={ - 'ordering': ['order'], - 'abstract': False, - }, - bases=(models.Model,), - ), - migrations.CreateModel( - name='GenericNote', - fields=[ - ('id', models.AutoField(auto_created=True, serialize=False, primary_key=True, verbose_name='ID')), - ('order', models.PositiveIntegerField(editable=False, default=1, db_index=True)), - ('title', models.CharField(max_length=50)), - ('object_id', models.PositiveIntegerField(verbose_name='Content id')), - ('content_type', models.ForeignKey(related_name='generic_notes', verbose_name='Content type', to='contenttypes.ContentType')), - ], - options={ - 'ordering': ['order'], - 'abstract': False, - }, - bases=(models.Model,), - ), - migrations.CreateModel( - name='Note', - fields=[ - ('id', models.AutoField(auto_created=True, serialize=False, primary_key=True, verbose_name='ID')), - ('order', models.PositiveIntegerField(editable=False, default=1, db_index=True)), - ('text', models.CharField(max_length=100)), - ], - options={ - 'ordering': ['order'], - 'abstract': False, - }, - bases=(models.Model,), - ), - migrations.CreateModel( - name='Person', - fields=[ - ('id', models.AutoField(auto_created=True, serialize=False, primary_key=True, verbose_name='ID')), - ('order', models.PositiveIntegerField(editable=False, default=1, db_index=True)), - ('first_name', models.CharField(max_length=50)), - ('last_name', models.CharField(max_length=50)), - ('is_board_member', models.BooleanField(verbose_name='Board Member', default=False)), - ], - options={ - 'ordering': ['order'], - 'verbose_name_plural': 'People', - 'abstract': False, - }, - bases=(models.Model,), - ), - migrations.CreateModel( - name='Project', - fields=[ - ('id', models.AutoField(auto_created=True, serialize=False, primary_key=True, verbose_name='ID')), - ('order', models.PositiveIntegerField(editable=False, default=1, db_index=True)), - ('title', models.CharField(max_length=50)), - ('description', models.TextField()), - ('category', adminsortable.fields.SortableForeignKey(to='app.Category')), - ], - options={ - 'ordering': ['order'], - 'abstract': False, - }, - bases=(models.Model,), - ), - migrations.CreateModel( - name='Widget', - fields=[ - ('id', models.AutoField(auto_created=True, serialize=False, primary_key=True, verbose_name='ID')), - ('order', models.PositiveIntegerField(editable=False, default=1, db_index=True)), - ('title', models.CharField(max_length=50)), - ], - options={ - 'ordering': ['order'], - 'abstract': False, - }, - bases=(models.Model,), - ), - migrations.AddField( - model_name='note', - name='project', - field=models.ForeignKey(to='app.Project'), - preserve_default=True, - ), - migrations.AddField( - model_name='credit', - name='project', - field=models.ForeignKey(to='app.Project'), - preserve_default=True, - ), - migrations.AddField( - model_name='component', - name='widget', - field=adminsortable.fields.SortableForeignKey(to='app.Widget'), - preserve_default=True, - ), - ] diff --git a/python3_sample_project/app/migrations/0002_nonsortablecategory_sortablecategorywidget.py b/python3_sample_project/app/migrations/0002_nonsortablecategory_sortablecategorywidget.py deleted file mode 100644 index 53db365..0000000 --- a/python3_sample_project/app/migrations/0002_nonsortablecategory_sortablecategorywidget.py +++ /dev/null @@ -1,44 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import models, migrations -import adminsortable.fields - - -class Migration(migrations.Migration): - - dependencies = [ - ('app', '0001_initial'), - ] - - operations = [ - migrations.CreateModel( - name='NonSortableCategory', - fields=[ - ('id', models.AutoField(serialize=False, auto_created=True, verbose_name='ID', primary_key=True)), - ('title', models.CharField(max_length=50)), - ], - options={ - 'verbose_name': 'Non-Sortable Category', - 'verbose_name_plural': 'Non-Sortable Categories', - 'abstract': False, - }, - bases=(models.Model,), - ), - migrations.CreateModel( - name='SortableCategoryWidget', - fields=[ - ('id', models.AutoField(serialize=False, auto_created=True, verbose_name='ID', primary_key=True)), - ('order', models.PositiveIntegerField(db_index=True, editable=False, default=1)), - ('title', models.CharField(max_length=50)), - ('non_sortable_category', adminsortable.fields.SortableForeignKey(to='app.NonSortableCategory')), - ], - options={ - 'ordering': ['order'], - 'verbose_name': 'Sortable Category Widget', - 'abstract': False, - 'verbose_name_plural': 'Sortable Category Widgets', - }, - bases=(models.Model,), - ), - ] diff --git a/python3_sample_project/app/migrations/0003_selfreferentialcategory.py b/python3_sample_project/app/migrations/0003_selfreferentialcategory.py deleted file mode 100644 index bd9a878..0000000 --- a/python3_sample_project/app/migrations/0003_selfreferentialcategory.py +++ /dev/null @@ -1,28 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import models, migrations -import adminsortable.fields - - -class Migration(migrations.Migration): - - dependencies = [ - ('app', '0002_nonsortablecategory_sortablecategorywidget'), - ] - - operations = [ - migrations.CreateModel( - name='SelfReferentialCategory', - fields=[ - ('id', models.AutoField(serialize=False, auto_created=True, primary_key=True, verbose_name='ID')), - ('order', models.PositiveIntegerField(db_index=True, editable=False, default=1)), - ('title', models.CharField(max_length=50)), - ('child', adminsortable.fields.SortableForeignKey(to='app.SelfReferentialCategory')), - ], - options={ - 'abstract': False, - }, - bases=(models.Model,), - ), - ] diff --git a/python3_sample_project/app/migrations/0004_auto_20141029_1612.py b/python3_sample_project/app/migrations/0004_auto_20141029_1612.py deleted file mode 100644 index 1f7e76f..0000000 --- a/python3_sample_project/app/migrations/0004_auto_20141029_1612.py +++ /dev/null @@ -1,24 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import models, migrations -import adminsortable.fields - - -class Migration(migrations.Migration): - - dependencies = [ - ('app', '0003_selfreferentialcategory'), - ] - - operations = [ - migrations.AlterModelOptions( - name='selfreferentialcategory', - options={'verbose_name_plural': 'Sortable Referential Categories', 'verbose_name': 'Sortable Referential Category'}, - ), - migrations.AlterField( - model_name='selfreferentialcategory', - name='child', - field=adminsortable.fields.SortableForeignKey(to='app.SelfReferentialCategory', null=True, blank=True), - ), - ] diff --git a/python3_sample_project/app/migrations/__init__.py b/python3_sample_project/app/migrations/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/python3_sample_project/app/models.py b/python3_sample_project/app/models.py deleted file mode 100644 index 34127b1..0000000 --- a/python3_sample_project/app/models.py +++ /dev/null @@ -1,169 +0,0 @@ -from django.contrib.contenttypes import generic -from django.contrib.contenttypes.models import ContentType -from django.db import models - -from adminsortable.fields import SortableForeignKey -from adminsortable.models import Sortable - - -class SimpleModel(models.Model): - class Meta: - abstract = True - - title = models.CharField(max_length=50) - - def __unicode__(self): - return self.title - - -# A model that is sortable -class Category(SimpleModel, Sortable): - class Meta(Sortable.Meta): - """ - Classes that inherit from Sortable must define an inner - Meta class that inherits from Sortable.Meta or ordering - won't work as expected - """ - verbose_name_plural = 'Categories' - - def __str__(self): - return self.title - - -# A model with an override of its queryset for admin -class Widget(SimpleModel, Sortable): - class Meta(Sortable.Meta): - pass - - def __str__(self): - return self.title - - -# A model that is sortable relative to a foreign key that is also sortable -# uses SortableForeignKey field. Works with versions 1.3+ -class Project(SimpleModel, Sortable): - class Meta(Sortable.Meta): - pass - - category = SortableForeignKey(Category) - description = models.TextField() - - -# Registered as a tabular inline on `Project` -class Credit(Sortable): - class Meta(Sortable.Meta): - pass - - project = models.ForeignKey(Project) - first_name = models.CharField(max_length=30) - last_name = models.CharField(max_length=30) - - def __str__(self): - return '{0} {1}'.format(self.first_name, self.last_name) - - -# Registered as a stacked inline on `Project` -class Note(Sortable): - class Meta(Sortable.Meta): - pass - - project = models.ForeignKey(Project) - text = models.CharField(max_length=100) - - def __str__(self): - return self.text - - -# A generic bound model -class GenericNote(SimpleModel, Sortable): - content_type = models.ForeignKey(ContentType, - verbose_name=u"Content type", related_name="generic_notes") - object_id = models.PositiveIntegerField(u"Content id") - content_object = generic.GenericForeignKey(ct_field='content_type', - fk_field='object_id') - - class Meta(Sortable.Meta): - pass - - def __str__(self): - return u'{0}: {1}'.format(self.title, self.content_object) - - -# An model registered as an inline that has a custom queryset -class Component(SimpleModel, Sortable): - class Meta(Sortable.Meta): - pass - - widget = SortableForeignKey(Widget) - - def __str__(self): - return self.title - - -class Person(Sortable): - class Meta(Sortable.Meta): - verbose_name_plural = 'People' - - first_name = models.CharField(max_length=50) - last_name = models.CharField(max_length=50) - is_board_member = models.BooleanField('Board Member', default=False) - - # Sorting Filters allow you to set up sub-sets of objects that need - # to have independent sorting. They are listed in order, from left - # to right in the sorting change list. You can use any standard - # Django ORM filter method. - sorting_filters = ( - ('Board Members', {'is_board_member': True}), - ('Non-Board Members', {'is_board_member': False}), - ) - - def __str__(self): - return '{0} {1}'.format(self.first_name, self.last_name) - - -class NonSortableCategory(SimpleModel): - class Meta(SimpleModel.Meta): - verbose_name = 'Non-Sortable Category' - verbose_name_plural = 'Non-Sortable Categories' - - def __str__(self): - return self.title - - -class SortableCategoryWidget(SimpleModel, Sortable): - class Meta(Sortable.Meta): - verbose_name = 'Sortable Category Widget' - verbose_name_plural = 'Sortable Category Widgets' - - non_sortable_category = SortableForeignKey(NonSortableCategory) - - def __str__(self): - return self.title - - -class SortableNonInlineCategory(SimpleModel, Sortable): - """Example of a model that is sortable, but has a SortableForeignKey - that is *not* sortable, and is also not defined as an inline of the - SortableForeignKey field.""" - - class Meta(Sortable.Meta): - verbose_name = 'Sortable Non-Inline Category' - verbose_name_plural = 'Sortable Non-Inline Categories' - - non_sortable_category = SortableForeignKey(NonSortableCategory) - - def __str__(self): - return self.title - - -class SelfReferentialCategory(SimpleModel, Sortable): - class Meta(Sortable.Meta): - verbose_name = 'Sortable Referential Category' - verbose_name_plural = 'Sortable Referential Categories' - - child = SortableForeignKey('self', blank=True, null=True) - - def __str__(self): - if self.child: - return '{} - {}'.format(self.child, self.title) - return self.title diff --git a/python3_sample_project/app/tests.py b/python3_sample_project/app/tests.py deleted file mode 100644 index 66e1a4b..0000000 --- a/python3_sample_project/app/tests.py +++ /dev/null @@ -1,158 +0,0 @@ -import http.client -import json - -from django.contrib.auth.models import User -from django.test import TestCase -from django.test.client import Client, RequestFactory - -from adminsortable.utils import get_is_sortable -from app.models import Category, Person - - -class SortableTestCase(TestCase): - fixtures = ['data.json'] - - def setUp(self): - self.client = Client() - self.factory = RequestFactory() - self.user_raw_password = 'admin' - self.user = User.objects.create_user('admin', 'admin@admin.com', - self.user_raw_password) - self.user.is_staff = True - self.user.is_superuser = True - self.user.save() - - people = Person.objects.all() - self.first_person = people[0] - self.second_person = people[1] - - def create_category(self, title='Category 1'): - category = Category.objects.create(title=title) - return category - - def test_new_user_is_authenticated(self): - self.assertEqual(self.user.is_authenticated(), True, - 'User is not authenticated') - - def test_new_user_is_staff(self): - self.assertEqual(self.user.is_staff, True, 'User is not staff') - - def test_is_not_sortable(self): - """ - A model should only become sortable if it has more than - record to sort. - """ - self.create_category() - self.assertFalse(get_is_sortable(Category.objects.all()), - 'Category only has one record. It should not be sortable.') - - def test_is_sortable(self): - self.create_category() - self.create_category(title='Category 2') - self.assertTrue(get_is_sortable(Category.objects.all()), - 'Category has more than one record. It should be sortable.') - - def test_save_order_incremented(self): - category1 = self.create_category() - self.assertEqual(category1.order, 1, 'Category 1 order should be 1.') - - category2 = self.create_category(title='Category 2') - self.assertEqual(category2.order, 2, 'Category 2 order should be 2.') - - 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/') - self.assertEquals(response.status_code, http.client.OK, - 'Unable to reach sort view.') - - def make_test_categories(self): - category1 = self.create_category() - category2 = self.create_category(title='Category 2') - category3 = self.create_category(title='Category 3') - return category1, category2, category3 - - def get_sorting_url(self): - return '/admin/app/category/sorting/do-sorting/{0}/'.format( - Category.model_type_id()) - - def get_category_indexes(self, *categories): - return {'indexes': ','.join([str(c.id) for c in categories])} - - def test_adminsortable_changelist_templates(self): - logged_in = self.client.login(username=self.user.username, - password=self.user_raw_password) - self.assertTrue(logged_in, 'User is not logged in') - - response = self.client.get('/admin/app/category/sort/') - self.assertEqual(response.status_code, http.client.OK, - 'Admin sort request failed.') - - #assert adminsortable change list templates are used - template_names = [t.name for t in response.templates] - self.assertTrue('adminsortable/change_list.html' in template_names, - 'adminsortable/change_list.html was not rendered') - - def test_adminsortable_change_list_sorting_fails_if_not_ajax(self): - logged_in = self.client.login(username=self.user.username, - password=self.user_raw_password) - self.assertTrue(logged_in, 'User is not logged in') - - category1, category2, category3 = self.make_test_categories() - #make a normal POST - response = self.client.post(self.get_sorting_url(), - data=self.get_category_indexes(category1, category2, category3)) - content = json.loads(response.content.decode(encoding='UTF-8'), - 'latin-1') - self.assertFalse(content.get('objects_sorted'), - 'Objects should not have been sorted. An ajax post is required.') - - def test_adminsortable_change_list_sorting_successful(self): - logged_in = self.client.login(username=self.user.username, - password=self.user_raw_password) - self.assertTrue(logged_in, 'User is not logged in') - - #make categories - category1, category2, category3 = self.make_test_categories() - - #make an Ajax POST - response = self.client.post(self.get_sorting_url(), - data=self.get_category_indexes(category3, category2, category1), - HTTP_X_REQUESTED_WITH='XMLHttpRequest') - content = json.loads(response.content.decode(encoding='UTF-8'), - 'latin-1') - self.assertTrue(content.get('objects_sorted'), - 'Objects should have been sorted.') - - #assert order is correct - categories = Category.objects.all() - cat1 = categories[0] - cat2 = categories[1] - cat3 = categories[2] - - self.assertEqual(cat1.order, 1, - 'First category returned should have order == 1') - self.assertEqual(cat1.pk, 3, - 'Category ID 3 should have been first in queryset') - - self.assertEqual(cat2.order, 2, - 'Second category returned should have order == 2') - self.assertEqual(cat2.pk, 2, - 'Category ID 2 should have been second in queryset') - - self.assertEqual(cat3.order, 3, - 'Third category returned should have order == 3') - self.assertEqual(cat3.pk, 1, - 'Category ID 1 should have been third in queryset') - - def test_get_next(self): - result = self.first_person.get_next() - - self.assertEqual(self.second_person, result, 'Next person should ' - 'be "{}"'.format(self.second_person)) - - def test_get_previous(self): - result = self.second_person.get_previous() - - self.assertEqual(self.first_person, result, 'Previous person should ' - 'be "{}"'.format(self.first_person)) diff --git a/python3_sample_project/database/python3-test-project.sqlite3 b/python3_sample_project/database/python3-test-project.sqlite3 deleted file mode 100644 index 95395d04c852e96d28a1deee9d199e66e388e701..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 84992 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 T*U-&aCISyT0>FIl) z^YNbZoO9ZPZ>k3e)PV)6Sj8CY9`vkI1+v;-@#F0;1m@_C9^K#MYiQE_D;w+m^^J|W zk$|tb%#NdE&ARa+-p4=icf5r^<5e8Zm548pZ}R1?u3zrOa`suqcHmT1B{qZ4tNUwp zU#-`8EMlOc&S*4pR}MVkbX;TtGk_U9izo071v-SiZV(J=urs=+&$D`KU$iH^d%s6_ zqeS^^)L@{|V}DAp?lnrv8%yn!s=Ha<1^5qZlN|WwJy>Jj04Lt<=@A zHI>@m@p6>F3aOEg6IBMJy?FH@{m1fx5myW`s?nb0-9P-K$B^Q(PyvJuS&fckH{I?}3{r-tV% zemW@`b9lbZ&}1f+nG?f}^9t}GU422|1^k{U`jMvfveko6F#FR>pscV`wMtcO7HO)K zs7PtEN>C($@}b(lLwDhIrs5#r2r)RAbKH0xopKOrr0?|e9e0mDA@0PejbL3>_iVJ z#VTH77N6sI8-KC({8$_*%eF%tNm>|DS(bc#}WWn)HVHd-_AIp_rLyiJ9T&l9Aqxb*8T?(H1oKMZ#u( zB(Y65dqb(N;JSEQ_Sln1r`_nQTwxxyLwm>nZxIcx~YDg>?Vww`9=ssv-s%&s&OQqBY zq$VVo=tHBeW0)7C^5BDk2W61a#6*qS#B740X{6<+{G=77B-Df&A|dtMX^U-)^Kf(K zoO8c(&Ue0x`vWlmDTv0_+sx1%_~wZ$#k|gyQQ@$yD6Q1ER{;R zBh8tzl?JX*HhUKL@fZHYZQR5STye|gFx+eHYg1UoF4{)_nFJ+m&7{&zjp=k_Ci5>? zswGQc8TVrUhG=AzN!SeE;ub!GO(@6E9g~vr2JFcn>Pv3x>dWuz={=lmia~kBa&Ok+ zl9>(5ooTAP@;?BXm{0(6d2Z(Ppeb<*B{%fJaqPf1EU2afBG8#>#;wk-V)1b2>v>#e zQ59KuqEctvwBn+z=cUf>Lflf^ zuI|^0`Q*-?zI-xcK_j$!EOllTTFjoYVy^t;fuV{^S`U#vLuCC;co$F+l2QZb@J|82 zG}XIw=T0IJyg>EOGg{PnH+1GFIM-g}+9Q&H)+lUs0(Y3k=+J#nh%p~dlQ6kE=ZQcV z)08yDaTim#;}=yhGA;$~GbzDM&A$Q#ps~|G3K_e>3`7`yAQBt#Dc(i_?R52?up_1V zE%O`Lkw1{{ExbHWK-v`51`(R2QT+WZi*BZGfH?m z#&l|O)(!nWjGY7Xb?D&7zi9fke*T%mZV=Rj1@#kdua-n}YrN(2yrQ*U~+k8>*)5W{?c?Pl-W<+9Bi-pyONH}DL9g6o^K zj$>~=X?O2TdT;FFD|jr7_h^I^LkgGhCHhHz&k=YvoK%h*&h;E$Q=cw3seu|UAO2vr ziSmH&(jL0ngmWUtEj8VGXClXI%G#e^4W z;Xh-&zcj^`^gl~2plsbxWC>*gial@cc`nKlILksJ!9+rA7X|UIaK)H-fLi(~6-j89 XykwCdCj~LK&VIFHop-f|*Tnt-03b}+ diff --git a/sample_project/sample_project/settings.py b/sample_project/sample_project/settings.py index e421ffb..f70e113 100644 --- a/sample_project/sample_project/settings.py +++ b/sample_project/sample_project/settings.py @@ -1,5 +1,11 @@ # Django settings for test_project project. -from utils import map_path +import os + + +def map_path(directory_name): + return os.path.join(os.path.dirname(__file__), + '../' + directory_name).replace('\\', '/') + DEBUG = True TEMPLATE_DEBUG = DEBUG From 7636e0e7297c44125dfbd56a65b88bb35db6f7f5 Mon Sep 17 00:00:00 2001 From: Brandon Taylor Date: Wed, 19 Nov 2014 11:05:44 -0500 Subject: [PATCH 2/7] Update Travis config. --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index db076ec..cf2b679 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,6 @@ env: - DJANGO_VERSION=1.5.10 SAMPLE_PROJECT=sample_project - DJANGO_VERSION=1.6.7 SAMPLE_PROJECT=sample_project - DJANGO_VERSION=1.7 SAMPLE_PROJECT=sample_project - - DJANGO_VERSION=1.7 SAMPLE_PROJECT=python3_sample_project branches: only: From ebda962dfe8f56c7393bafe5cc6d1ce35ff6445b Mon Sep 17 00:00:00 2001 From: Brandon Taylor Date: Wed, 19 Nov 2014 11:07:05 -0500 Subject: [PATCH 3/7] Update Travis config. --- .travis.yml | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/.travis.yml b/.travis.yml index cf2b679..1c9c45a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,6 @@ language: python python: - - "2.6" - "2.7" - "3.4" @@ -16,18 +15,6 @@ branches: matrix: exclude: - - - python: "2.6" - env: DJANGO_VERSION=1.5.10 SAMPLE_PROJECT=sample_project - - - - python: "2.6" - env: DJANGO_VERSION=1.7 SAMPLE_PROJECT=sample_project - - - - python: "2.6" - env: DJANGO_VERSION=1.7 SAMPLE_PROJECT=python3_sample_project - - python: "2.7" env: DJANGO_VERSION=1.5.10 SAMPLE_PROJECT=sample_project From dfc654121cfded3662e8a1cee4b02233b31b7689 Mon Sep 17 00:00:00 2001 From: Brandon Taylor Date: Wed, 19 Nov 2014 11:10:28 -0500 Subject: [PATCH 4/7] Version to 1.7.8. Updated readme. --- README.md | 5 +++-- adminsortable/__init__.py | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 985926b..88f62b7 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![Build Status](https://travis-ci.org/iambrandontaylor/django-admin-sortable.svg?branch=master)](https://travis-ci.org/iambrandontaylor/django-admin-sortable) -Current version: 1.7.7 +Current version: 1.7.8 This project makes it easy to add drag-and-drop ordering to any model in Django admin. Inlines for a sortable model may also be made sortable, @@ -409,8 +409,9 @@ ordering on top of that just seemed a little much in my opinion. django-admin-sortable is currently used in production. -### What's new in 1.7.7? +### What's new in 1.7.8? - Limited support for self-referential SortableForeignKeys +- Improved support for sortable models that have a foreign key to a non-sortable parent ### Deprecation warnings diff --git a/adminsortable/__init__.py b/adminsortable/__init__.py index 59bb9fa..d9ba222 100644 --- a/adminsortable/__init__.py +++ b/adminsortable/__init__.py @@ -1,4 +1,4 @@ -VERSION = (1, 7, 7) # following PEP 386 +VERSION = (1, 7, 8) # following PEP 386 DEV_N = None From cf1a2103dda7ce70a0e7d24de06ef54df6ef0910 Mon Sep 17 00:00:00 2001 From: matt-leach Date: Mon, 22 Dec 2014 14:36:15 +0000 Subject: [PATCH 5/7] Updating VERSION comparison to be compatible with all 1.5.x --- adminsortable/admin.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/adminsortable/admin.py b/adminsortable/admin.py index bd7fab3..6610ebf 100644 --- a/adminsortable/admin.py +++ b/adminsortable/admin.py @@ -291,7 +291,7 @@ class SortableInlineBase(SortableAdminBase, InlineModelAdmin): class SortableTabularInline(TabularInline, SortableInlineBase): """Custom template that enables sorting for tabular inlines""" - if VERSION <= (1, 5): + if VERSION < (1, 6): template = 'adminsortable/edit_inline/tabular-1.5.x.html' else: template = 'adminsortable/edit_inline/tabular.html' @@ -299,7 +299,7 @@ class SortableTabularInline(TabularInline, SortableInlineBase): class SortableStackedInline(StackedInline, SortableInlineBase): """Custom template that enables sorting for stacked inlines""" - if VERSION <= (1, 5): + if VERSION < (1, 6): template = 'adminsortable/edit_inline/stacked-1.5.x.html' else: template = 'adminsortable/edit_inline/stacked.html' @@ -307,7 +307,7 @@ class SortableStackedInline(StackedInline, SortableInlineBase): class SortableGenericTabularInline(GenericTabularInline, SortableInlineBase): """Custom template that enables sorting for tabular inlines""" - if VERSION <= (1, 5): + if VERSION < (1, 6): template = 'adminsortable/edit_inline/tabular-1.5.x.html' else: template = 'adminsortable/edit_inline/tabular.html' @@ -315,7 +315,7 @@ class SortableGenericTabularInline(GenericTabularInline, SortableInlineBase): class SortableGenericStackedInline(GenericStackedInline, SortableInlineBase): """Custom template that enables sorting for stacked inlines""" - if VERSION <= (1, 5): + if VERSION < (1, 6): template = 'adminsortable/edit_inline/stacked-1.5.x.html' else: template = 'adminsortable/edit_inline/stacked.html' From c7f2d63ec9d6b3141673f51a01b43d95e8d523ad Mon Sep 17 00:00:00 2001 From: matt-leach Date: Mon, 22 Dec 2014 14:44:02 +0000 Subject: [PATCH 6/7] calling the correct queryset/get_queryset for VERSION --- adminsortable/admin.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/adminsortable/admin.py b/adminsortable/admin.py index 6610ebf..3625cab 100644 --- a/adminsortable/admin.py +++ b/adminsortable/admin.py @@ -278,7 +278,11 @@ class SortableInlineBase(SortableAdminBase, InlineModelAdmin): ' and SortableStackedInline must inherit from Sortable') def get_queryset(self, request): - qs = super(SortableInlineBase, self).get_queryset(request) + if VERSION < (1, 6): + qs = super(SortableInlineBase, self).queryset(request) + else: + qs = super(SortableInlineBase, self).get_queryset(request) + if get_is_sortable(qs): self.model.is_sortable = True else: From e0b38fb705a16856c57e8cd91c79449708083519 Mon Sep 17 00:00:00 2001 From: matt-leach Date: Mon, 22 Dec 2014 14:57:17 +0000 Subject: [PATCH 7/7] Using __class__ to get model class as model is not an attribute of class Meta in Django 1.5.x --- adminsortable/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adminsortable/models.py b/adminsortable/models.py index 2e9d907..d17a815 100644 --- a/adminsortable/models.py +++ b/adminsortable/models.py @@ -80,7 +80,7 @@ class Sortable(models.Model): {self.sortable_foreign_key.name: sfk_obj.id}) try: - obj = self._meta.model.objects.filter(**filters)[:1][0] + obj = self.__class__.objects.filter(**filters)[:1][0] except IndexError: obj = None