Refactored sortable_by into a property instead of a classmethod.

Added backwards compatibility for pre 1.1.1 versions that still have sortable_by defined as a classmethod.
Need to address dynamic regroup template tag to see why categories are not being grouped properly in sample app.
master
unknown 2011-11-22 20:42:36 -06:00
parent fba568399c
commit 1b9c5c0a64
10 changed files with 107 additions and 15 deletions

View File

@ -53,13 +53,18 @@ class SortableAdmin(ModelAdmin):
has_perm = request.user.has_perm(opts.app_label + '.' + opts.get_change_permission()) has_perm = request.user.has_perm(opts.app_label + '.' + opts.get_change_permission())
objects = self.model.objects.all() objects = self.model.objects.all()
""" #Determine if we need to regroup objects relative to a foreign key specified on the
Determine if we need to regroup objects relative to a foreign key specified on the # model class that is extending Sortable.
model class that is extending Sortable.
"""
sortable_by = getattr(self.model, 'sortable_by', None) sortable_by = getattr(self.model, 'sortable_by', None)
if sortable_by: if 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() 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_display_name = sortable_by_class._meta.verbose_name_plural
sortable_by_class_is_sortable = sortable_by_class.is_sortable() sortable_by_class_is_sortable = sortable_by_class.is_sortable()
else: else:

View File

@ -14,8 +14,12 @@ class Sortable(models.Model):
`model_type_id` returns the ContentType.id for the Model that inherits Sortable `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 `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) order = models.PositiveIntegerField(editable=False, default=1, db_index=True)
sortable_by = None
class Meta: class Meta:
abstract = True abstract = True

View File

@ -69,7 +69,7 @@ def dynamic_regroup(parser, token):
""" """
expression = lastbits_reversed[2][::-1] expression = lastbits_reversed[2][::-1]
var_name = lastbits_reversed[0][::-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 We also need to hand the parser to the node in order to convert the value
for `expression` to a FilterExpression. for `expression` to a FilterExpression.

Binary file not shown.

View File

@ -1,7 +1,7 @@
from django.contrib import admin from django.contrib import admin
from adminsortable.admin import SortableAdmin, SortableTabularInline, SortableStackedInline 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) admin.site.register(Category, SortableAdmin)
@ -20,3 +20,4 @@ class ProjectAdmin(SortableAdmin):
list_display = ['__unicode__', 'category'] list_display = ['__unicode__', 'category']
admin.site.register(Project, ProjectAdmin) admin.site.register(Project, ProjectAdmin)
admin.site.register(Sample, SortableAdmin)

View File

@ -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']

View File

@ -29,13 +29,28 @@ class Project(SimpleModel, Sortable):
class Meta(Sortable.Meta): class Meta(Sortable.Meta):
pass pass
@classmethod # @classmethod
def sortable_by(cls): # def sortable_by(cls):
return Category, 'category' # return Category, 'category'
category = models.ForeignKey(Category) category = models.ForeignKey(Category)
description = models.TextField() 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 #registered as a tabular inline on project
class Credit(Sortable): class Credit(Sortable):

View File

@ -1,12 +1,9 @@
import httplib import httplib
import json import json
from django.contrib.auth.forms import authenticate, UserCreationForm
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.middleware import csrf
from django.db import models from django.db import models
from django.template.defaultfilters import urlencode
from django.test import TestCase from django.test import TestCase
from django.test.client import Client, RequestFactory from django.test.client import Client, RequestFactory
@ -83,6 +80,9 @@ class SortableTestCase(TestCase):
def get_category_indexes(self, *categories): def get_category_indexes(self, *categories):
return {'indexes' : ','.join([str(c.id) for c in 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): def test_adminsortable_changelist_templates(self):
logged_in = self.client.login(username=self.user.username, password=self.user_raw_password) logged_in = self.client.login(username=self.user.username, password=self.user_raw_password)
self.assertTrue(logged_in, 'User is not logged in') self.assertTrue(logged_in, 'User is not logged in')

View File

@ -102,7 +102,6 @@ MIDDLEWARE_CLASSES = (
'django.middleware.csrf.CsrfViewMiddleware', 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware', 'django.contrib.messages.middleware.MessageMiddleware',
'debug_toolbar.middleware.DebugToolbarMiddleware',
) )
TEMPLATE_CONTEXT_PROCESSORS = ( TEMPLATE_CONTEXT_PROCESSORS = (