diff --git a/adminsortable/admin.py b/adminsortable/admin.py index f80064a..b389546 100755 --- a/adminsortable/admin.py +++ b/adminsortable/admin.py @@ -53,13 +53,18 @@ class SortableAdmin(ModelAdmin): has_perm = request.user.has_perm(opts.app_label + '.' + opts.get_change_permission()) objects = self.model.objects.all() - """ - Determine if we need to regroup objects relative to a foreign key specified on the - model class that is extending Sortable. - """ + #Determine if we need to regroup objects relative to a foreign key specified on the + # model class that is extending Sortable. sortable_by = getattr(self.model, 'sortable_by', None) if sortable_by: - sortable_by_class, sortable_by_expression = sortable_by() + #backwards compatibility for < 1.1.1, where sortable_by was a classmethod instead of a property + try: + sortable_by_class, sortable_by_expression = sortable_by() + except ValueError: + sortable_by_class = self.model.sortable_by + sortable_by_expression = sortable_by_class.__name__.lower() + + print sortable_by_expression sortable_by_class_display_name = sortable_by_class._meta.verbose_name_plural sortable_by_class_is_sortable = sortable_by_class.is_sortable() else: diff --git a/adminsortable/models.py b/adminsortable/models.py index 0d74262..af299de 100755 --- a/adminsortable/models.py +++ b/adminsortable/models.py @@ -14,8 +14,12 @@ class Sortable(models.Model): `model_type_id` returns the ContentType.id for the Model that inherits Sortable `save` the override of save increments the last/highest value of order by 1 + + Override `sortable_by` method to make your model be sortable by a foreign key field. + Set `sortable_by` to the class specified in the foreign key relationship. """ order = models.PositiveIntegerField(editable=False, default=1, db_index=True) + sortable_by = None class Meta: abstract = True diff --git a/adminsortable/templates/adminsortable/change_list.html b/adminsortable/templates/adminsortable/change_list.html index f5e7562..9d85464 100755 --- a/adminsortable/templates/adminsortable/change_list.html +++ b/adminsortable/templates/adminsortable/change_list.html @@ -55,7 +55,7 @@ {% if objects %}
{% if group_expression %} - {% render_nested_sortable_objects objects group_expression %} + {% render_nested_sortable_objects objects group_expression %} {% else %} {% render_sortable_objects objects %} {% endif %} diff --git a/adminsortable/templatetags/django_template_additions.py b/adminsortable/templatetags/django_template_additions.py index 252b2e8..4de7630 100755 --- a/adminsortable/templatetags/django_template_additions.py +++ b/adminsortable/templatetags/django_template_additions.py @@ -69,7 +69,7 @@ def dynamic_regroup(parser, token): """ expression = lastbits_reversed[2][::-1] var_name = lastbits_reversed[0][::-1] - + print expression """ We also need to hand the parser to the node in order to convert the value for `expression` to a FilterExpression. diff --git a/sample_project/adminsortable.sqlite b/sample_project/adminsortable.sqlite index 5f71f74..df95757 100755 Binary files a/sample_project/adminsortable.sqlite and b/sample_project/adminsortable.sqlite differ diff --git a/sample_project/app/admin.py b/sample_project/app/admin.py index a1eb445..f365aab 100755 --- a/sample_project/app/admin.py +++ b/sample_project/app/admin.py @@ -1,7 +1,7 @@ from django.contrib import admin from adminsortable.admin import SortableAdmin, SortableTabularInline, SortableStackedInline -from app.models import Category, Project, Credit, Note +from app.models import Category, Project, Credit, Note, Sample admin.site.register(Category, SortableAdmin) @@ -20,3 +20,4 @@ class ProjectAdmin(SortableAdmin): list_display = ['__unicode__', 'category'] admin.site.register(Project, ProjectAdmin) +admin.site.register(Sample, SortableAdmin) diff --git a/sample_project/app/migrations/0003_add_sample.py b/sample_project/app/migrations/0003_add_sample.py new file mode 100644 index 0000000..f683706 --- /dev/null +++ b/sample_project/app/migrations/0003_add_sample.py @@ -0,0 +1,68 @@ +# encoding: utf-8 +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + +class Migration(SchemaMigration): + + def forwards(self, orm): + + # Adding model 'Sample' + db.create_table('app_sample', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('order', self.gf('django.db.models.fields.PositiveIntegerField')(default=1, db_index=True)), + ('title', self.gf('django.db.models.fields.CharField')(max_length=50)), + ('category', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['app.Category'])), + ('description', self.gf('django.db.models.fields.TextField')()), + )) + db.send_create_signal('app', ['Sample']) + + + def backwards(self, orm): + + # Deleting model 'Sample' + db.delete_table('app_sample') + + + models = { + 'app.category': { + 'Meta': {'ordering': "['order']", 'object_name': 'Category'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'order': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1', 'db_index': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'app.credit': { + 'Meta': {'ordering': "['order']", 'object_name': 'Credit'}, + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30'}), + 'order': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1', 'db_index': 'True'}), + 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['app.Project']"}) + }, + 'app.note': { + 'Meta': {'ordering': "['order']", 'object_name': 'Note'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'order': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1', 'db_index': 'True'}), + 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['app.Project']"}), + 'text': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'app.project': { + 'Meta': {'ordering': "['order']", 'object_name': 'Project'}, + 'category': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['app.Category']"}), + 'description': ('django.db.models.fields.TextField', [], {}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'order': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1', 'db_index': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'app.sample': { + 'Meta': {'ordering': "['order']", 'object_name': 'Sample'}, + 'category': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['app.Category']"}), + 'description': ('django.db.models.fields.TextField', [], {}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'order': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1', 'db_index': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + } + } + + complete_apps = ['app'] diff --git a/sample_project/app/models.py b/sample_project/app/models.py index caba787..2e8aab0 100755 --- a/sample_project/app/models.py +++ b/sample_project/app/models.py @@ -29,13 +29,28 @@ class Project(SimpleModel, Sortable): class Meta(Sortable.Meta): pass - @classmethod - def sortable_by(cls): - return Category, 'category' +# @classmethod +# def sortable_by(cls): +# return Category, 'category' category = models.ForeignKey(Category) description = models.TextField() + sortable_by = Category + + +#a model that is sortable relative to a foreign key that is also sortable +class Sample(SimpleModel, Sortable): + class Meta(Sortable.Meta): + pass + + category = models.ForeignKey(Category) + description = models.TextField() + + #field to define which foreign key the model is sortable by. + #works with versions > 1.1.1 + sortable_by = Category + #registered as a tabular inline on project class Credit(Sortable): diff --git a/sample_project/app/tests.py b/sample_project/app/tests.py index 3eb1677..13a59ad 100755 --- a/sample_project/app/tests.py +++ b/sample_project/app/tests.py @@ -1,12 +1,9 @@ import httplib import json -from django.contrib.auth.forms import authenticate, UserCreationForm from django.contrib.auth.models import User from django.core.urlresolvers import reverse -from django.middleware import csrf from django.db import models -from django.template.defaultfilters import urlencode from django.test import TestCase from django.test.client import Client, RequestFactory @@ -83,6 +80,9 @@ class SortableTestCase(TestCase): def get_category_indexes(self, *categories): return {'indexes' : ','.join([str(c.id) for c in categories])} + def test_sortable_by_backwards_compatibility(self): + pass + 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') diff --git a/sample_project/settings.py b/sample_project/settings.py index c16655e..0309bf8 100755 --- a/sample_project/settings.py +++ b/sample_project/settings.py @@ -102,7 +102,6 @@ MIDDLEWARE_CLASSES = ( 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', - 'debug_toolbar.middleware.DebugToolbarMiddleware', ) TEMPLATE_CONTEXT_PROCESSORS = (