Work in progress on refactoring the Sortable class into a non-obtrusive mixin.

master
Brandon Taylor 2015-08-23 22:23:45 -04:00
parent 422343ff93
commit b14d747f82
3 changed files with 63 additions and 39 deletions

View File

@ -4,7 +4,7 @@ from django.db import models
from django.utils.encoding import python_2_unicode_compatible from django.utils.encoding import python_2_unicode_compatible
from adminsortable.fields import SortableForeignKey from adminsortable.fields import SortableForeignKey
from adminsortable.models import Sortable from adminsortable.models import Sortable, SortableMixin
@python_2_unicode_compatible @python_2_unicode_compatible
@ -19,59 +19,65 @@ class SimpleModel(models.Model):
# A model that is sortable # A model that is sortable
class Category(SimpleModel, Sortable): class Category(SimpleModel, SortableMixin):
class Meta(Sortable.Meta): class 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' verbose_name_plural = 'Categories'
ordering = ['order']
order = models.PositiveIntegerField(default=0, editable=False)
# A model with an override of its queryset for admin # A model with an override of its queryset for admin
@python_2_unicode_compatible @python_2_unicode_compatible
class Widget(SimpleModel, Sortable): class Widget(SimpleModel, SortableMixin):
class Meta(Sortable.Meta): class Meta:
pass ordering = ['order']
def __str__(self): def __str__(self):
return self.title return self.title
order = models.PositiveIntegerField(default=0, editable=False)
# A model that is sortable relative to a foreign key that is also sortable # A model that is sortable relative to a foreign key that is also sortable
# uses SortableForeignKey field. Works with versions 1.3+ # uses SortableForeignKey field. Works with versions 1.3+
class Project(SimpleModel, Sortable): class Project(SimpleModel, SortableMixin):
class Meta(Sortable.Meta): class Meta:
pass ordering = ['order']
category = SortableForeignKey(Category) category = SortableForeignKey(Category)
description = models.TextField() description = models.TextField()
order = models.PositiveIntegerField(default=0, editable=False)
# Registered as a tabular inline on `Project` # Registered as a tabular inline on `Project`
@python_2_unicode_compatible @python_2_unicode_compatible
class Credit(Sortable): class Credit(SortableMixin):
class Meta(Sortable.Meta): class Meta:
pass ordering = ['order']
project = models.ForeignKey(Project) project = models.ForeignKey(Project)
first_name = models.CharField(max_length=30) first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30) last_name = models.CharField(max_length=30)
order = models.PositiveIntegerField(default=0, editable=False)
def __str__(self): def __str__(self):
return '{0} {1}'.format(self.first_name, self.last_name) return '{0} {1}'.format(self.first_name, self.last_name)
# Registered as a stacked inline on `Project` # Registered as a stacked inline on `Project`
@python_2_unicode_compatible @python_2_unicode_compatible
class Note(Sortable): class Note(SortableMixin):
class Meta(Sortable.Meta): class Meta:
pass ordering = ['order']
project = models.ForeignKey(Project) project = models.ForeignKey(Project)
text = models.CharField(max_length=100) text = models.CharField(max_length=100)
order = models.PositiveIntegerField(default=0, editable=False)
def __str__(self): def __str__(self):
return self.text return self.text
@ -99,15 +105,17 @@ class NonSortableNote(models.Model):
# A generic bound model # A generic bound model
@python_2_unicode_compatible @python_2_unicode_compatible
class GenericNote(SimpleModel, Sortable): class GenericNote(SimpleModel, SortableMixin):
content_type = models.ForeignKey(ContentType, content_type = models.ForeignKey(ContentType,
verbose_name=u"Content type", related_name="generic_notes") verbose_name=u"Content type", related_name="generic_notes")
object_id = models.PositiveIntegerField(u"Content id") object_id = models.PositiveIntegerField(u"Content id")
content_object = generic.GenericForeignKey(ct_field='content_type', content_object = generic.GenericForeignKey(ct_field='content_type',
fk_field='object_id') fk_field='object_id')
class Meta(Sortable.Meta): order = models.PositiveIntegerField(default=0, editable=False)
pass
class Meta:
ordering = ['order']
def __str__(self): def __str__(self):
return u'{0}: {1}'.format(self.title, self.content_object) return u'{0}: {1}'.format(self.title, self.content_object)
@ -115,25 +123,30 @@ class GenericNote(SimpleModel, Sortable):
# An model registered as an inline that has a custom queryset # An model registered as an inline that has a custom queryset
@python_2_unicode_compatible @python_2_unicode_compatible
class Component(SimpleModel, Sortable): class Component(SimpleModel, SortableMixin):
class Meta(Sortable.Meta): class Meta:
pass ordering = ['order']
widget = SortableForeignKey(Widget) widget = SortableForeignKey(Widget)
order = models.PositiveIntegerField(default=0, editable=False)
def __str__(self): def __str__(self):
return self.title return self.title
@python_2_unicode_compatible @python_2_unicode_compatible
class Person(Sortable): class Person(SortableMixin):
class Meta(Sortable.Meta): class Meta:
ordering = ['order']
verbose_name_plural = 'People' verbose_name_plural = 'People'
first_name = models.CharField(max_length=50) first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50) last_name = models.CharField(max_length=50)
is_board_member = models.BooleanField('Board Member', default=False) is_board_member = models.BooleanField('Board Member', default=False)
order = models.PositiveIntegerField(default=0, editable=False)
# Sorting Filters allow you to set up sub-sets of objects that need # 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 have independent sorting. They are listed in order, from left
# to right in the sorting change list. You can use any standard # to right in the sorting change list. You can use any standard
@ -158,26 +171,32 @@ class NonSortableCategory(SimpleModel):
@python_2_unicode_compatible @python_2_unicode_compatible
class SortableCategoryWidget(SimpleModel, Sortable): class SortableCategoryWidget(SimpleModel, SortableMixin):
class Meta(Sortable.Meta): class Meta:
ordering = ['order']
verbose_name = 'Sortable Category Widget' verbose_name = 'Sortable Category Widget'
verbose_name_plural = 'Sortable Category Widgets' verbose_name_plural = 'Sortable Category Widgets'
non_sortable_category = SortableForeignKey(NonSortableCategory) non_sortable_category = SortableForeignKey(NonSortableCategory)
order = models.PositiveIntegerField(default=0, editable=False)
def __str__(self): def __str__(self):
return self.title return self.title
@python_2_unicode_compatible @python_2_unicode_compatible
class SortableNonInlineCategory(SimpleModel, Sortable): class SortableNonInlineCategory(SimpleModel, SortableMixin):
"""Example of a model that is sortable, but has a SortableForeignKey """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 that is *not* sortable, and is also not defined as an inline of the
SortableForeignKey field.""" SortableForeignKey field."""
non_sortable_category = SortableForeignKey(NonSortableCategory) non_sortable_category = SortableForeignKey(NonSortableCategory)
class Meta(Sortable.Meta): order = models.PositiveIntegerField(default=0, editable=False)
class Meta:
ordering = ['order']
verbose_name = 'Sortable Non-Inline Category' verbose_name = 'Sortable Non-Inline Category'
verbose_name_plural = 'Sortable Non-Inline Categories' verbose_name_plural = 'Sortable Non-Inline Categories'

View File

@ -10,14 +10,19 @@ from django.db import models
from django.test import TestCase from django.test import TestCase
from django.test.client import Client from django.test.client import Client
from adminsortable.models import Sortable from adminsortable.models import SortableMixin
from adminsortable.utils import get_is_sortable from adminsortable.utils import get_is_sortable
from app.models import Category, Person, Project from app.models import Category, Person, Project
class TestSortableModel(Sortable): class TestSortableModel(SortableMixin):
title = models.CharField(max_length=100) title = models.CharField(max_length=100)
order = models.PositiveIntegerField(default=0, editable=False)
class Meta:
ordering = ['order']
def __unicode__(self): def __unicode__(self):
return self.title return self.title
@ -110,7 +115,7 @@ class SortableTestCase(TestCase):
self.assertEqual(response.status_code, httplib.OK, self.assertEqual(response.status_code, httplib.OK,
'Admin sort request failed.') 'Admin sort request failed.')
#assert adminsortable change list templates are used # assert adminsortable change list templates are used
template_names = [t.name for t in response.templates] template_names = [t.name for t in response.templates]
self.assertTrue('adminsortable/change_list.html' in template_names, self.assertTrue('adminsortable/change_list.html' in template_names,
'adminsortable/change_list.html was not rendered') 'adminsortable/change_list.html was not rendered')
@ -121,7 +126,7 @@ class SortableTestCase(TestCase):
self.assertTrue(logged_in, 'User is not logged in') self.assertTrue(logged_in, 'User is not logged in')
category1, category2, category3 = self.make_test_categories() category1, category2, category3 = self.make_test_categories()
#make a normal POST # make a normal POST
response = self.client.post(self.get_sorting_url(), response = self.client.post(self.get_sorting_url(),
data=self.get_category_indexes(category1, category2, category3)) data=self.get_category_indexes(category1, category2, category3))
content = json.loads(response.content.decode(encoding='UTF-8'), content = json.loads(response.content.decode(encoding='UTF-8'),
@ -134,10 +139,10 @@ class SortableTestCase(TestCase):
password=self.user_raw_password) password=self.user_raw_password)
self.assertTrue(logged_in, 'User is not logged in') self.assertTrue(logged_in, 'User is not logged in')
#make categories # make categories
category1, category2, category3 = self.make_test_categories() category1, category2, category3 = self.make_test_categories()
#make an Ajax POST # make an Ajax POST
response = self.client.post(self.get_sorting_url(), response = self.client.post(self.get_sorting_url(),
data=self.get_category_indexes(category3, category2, category1), data=self.get_category_indexes(category3, category2, category1),
HTTP_X_REQUESTED_WITH='XMLHttpRequest') HTTP_X_REQUESTED_WITH='XMLHttpRequest')
@ -146,7 +151,7 @@ class SortableTestCase(TestCase):
self.assertTrue(content.get('objects_sorted'), self.assertTrue(content.get('objects_sorted'),
'Objects should have been sorted.') 'Objects should have been sorted.')
#assert order is correct # assert order is correct
categories = Category.objects.all() categories = Category.objects.all()
cat1 = categories[0] cat1 = categories[0]
cat2 = categories[1] cat2 = categories[1]