mirror of
https://github.com/jazzband/django-admin-sortable.git
synced 2026-03-16 22:10:30 +00:00
Added SortableForeignKey field to replace sortable_by model property.
Refactored how the sortable_by properties get populated by looping over the model fields until we get to the SortableForeignKey, then grabbing properties from the field and its related data.
This commit is contained in:
parent
63a80f5953
commit
37f91cce97
80 changed files with 135 additions and 239 deletions
0
.gitignore
vendored
Executable file → Normal file
0
.gitignore
vendored
Executable file → Normal file
0
AUTHORS
Executable file → Normal file
0
AUTHORS
Executable file → Normal file
0
COPYRIGHT
Executable file → Normal file
0
COPYRIGHT
Executable file → Normal file
0
MANIFEST.in
Executable file → Normal file
0
MANIFEST.in
Executable file → Normal file
0
README
Executable file → Normal file
0
README
Executable file → Normal file
2
adminsortable/__init__.py
Executable file → Normal file
2
adminsortable/__init__.py
Executable file → Normal file
|
|
@ -1,4 +1,4 @@
|
|||
VERSION = (1, 2, "f", 0) # following PEP 386
|
||||
VERSION = (1, 3, "f", 0) # following PEP 386
|
||||
DEV_N = None
|
||||
|
||||
|
||||
|
|
|
|||
38
adminsortable/admin.py
Executable file → Normal file
38
adminsortable/admin.py
Executable file → Normal file
|
|
@ -9,6 +9,7 @@ from django.shortcuts import render
|
|||
from django.template.defaultfilters import capfirst
|
||||
from django.views.decorators.csrf import csrf_exempt
|
||||
|
||||
from adminsortable.fields import SortableForeignKey
|
||||
from adminsortable.models import Sortable
|
||||
|
||||
STATIC_URL = settings.STATIC_URL
|
||||
|
|
@ -20,8 +21,17 @@ class SortableAdmin(ModelAdmin):
|
|||
class Meta:
|
||||
abstract = True
|
||||
|
||||
def _get_sortable_foreign_key(self):
|
||||
sortable_foreign_key = None
|
||||
for field in self.model._meta.fields:
|
||||
if isinstance(field, SortableForeignKey):
|
||||
sortable_foreign_key = field
|
||||
break
|
||||
return sortable_foreign_key
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(SortableAdmin, self).__init__(*args, **kwargs)
|
||||
|
||||
self.has_sortable_tabular_inlines = False
|
||||
self.has_sortable_stacked_inlines = False
|
||||
for klass in self.inlines:
|
||||
|
|
@ -55,11 +65,16 @@ class SortableAdmin(ModelAdmin):
|
|||
|
||||
#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:
|
||||
#Legacy support for 'sortable_by' defined as a model property
|
||||
sortable_by_property = getattr(self.model, 'sortable_by', None)
|
||||
|
||||
#`sortable_by` defined as a SortableForeignKey
|
||||
sortable_by_fk = self._get_sortable_foreign_key()
|
||||
|
||||
if sortable_by_property:
|
||||
#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_property()
|
||||
except TypeError, ValueError:
|
||||
sortable_by_class = self.model.sortable_by
|
||||
sortable_by_expression = sortable_by_class.__name__.lower()
|
||||
|
|
@ -67,15 +82,24 @@ class SortableAdmin(ModelAdmin):
|
|||
sortable_by_class_display_name = sortable_by_class._meta.verbose_name_plural
|
||||
sortable_by_class_is_sortable = sortable_by_class.is_sortable()
|
||||
|
||||
elif sortable_by_fk:
|
||||
#get sortable by properties from the SortableForeignKey field - supported in 1.3+
|
||||
sortable_by_class_display_name = sortable_by_fk.rel.to._meta.verbose_name_plural
|
||||
sortable_by_class = sortable_by_fk.rel.to
|
||||
sortable_by_expression = sortable_by_fk.name.lower()
|
||||
sortable_by_class_is_sortable = sortable_by_class.is_sortable()
|
||||
|
||||
else:
|
||||
#model is not sortable by another model
|
||||
sortable_by_class = sortable_by_expression = sortable_by_class_display_name =\
|
||||
sortable_by_class_is_sortable = None
|
||||
|
||||
if sortable_by_property or sortable_by_fk:
|
||||
# Order the objects by the property they are sortable by, then by the order, otherwise the regroup
|
||||
# template tag will not show the objects correctly as
|
||||
# shown in https://docs.djangoproject.com/en/1.3/ref/templates/builtins/#regroup
|
||||
objects = objects.order_by(sortable_by_expression, 'order')
|
||||
|
||||
else:
|
||||
sortable_by_class = sortable_by_expression = sortable_by_class_display_name =\
|
||||
sortable_by_class_is_sortable = None
|
||||
|
||||
try:
|
||||
verbose_name_plural = opts.verbose_name_plural.__unicode__()
|
||||
except AttributeError:
|
||||
|
|
|
|||
9
adminsortable/fields.py
Normal file
9
adminsortable/fields.py
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
from django.db.models.fields.related import ForeignKey
|
||||
|
||||
|
||||
class SortableForeignKey(ForeignKey):
|
||||
"""
|
||||
Field simply acts as a flag to determine the class to sort by.
|
||||
This field replaces previous functionality where `sortable_by` was definied as a model property
|
||||
that specified another model class.
|
||||
"""
|
||||
0
adminsortable/locale/en/LC_MESSAGES/django.po
Executable file → Normal file
0
adminsortable/locale/en/LC_MESSAGES/django.po
Executable file → Normal file
0
adminsortable/locale/nl/LC_MESSAGES/django.mo
Executable file → Normal file
0
adminsortable/locale/nl/LC_MESSAGES/django.mo
Executable file → Normal file
0
adminsortable/locale/nl/LC_MESSAGES/django.po
Executable file → Normal file
0
adminsortable/locale/nl/LC_MESSAGES/django.po
Executable file → Normal file
24
adminsortable/models.py
Executable file → Normal file
24
adminsortable/models.py
Executable file → Normal file
|
|
@ -1,6 +1,16 @@
|
|||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.db import models
|
||||
|
||||
from adminsortable.fields import SortableForeignKey
|
||||
|
||||
|
||||
class MultipleSortableForeignKeyException(Exception):
|
||||
def __init__(self, value):
|
||||
self.value = value
|
||||
|
||||
def __str__(self):
|
||||
return repr(self.value)
|
||||
|
||||
|
||||
class Sortable(models.Model):
|
||||
"""
|
||||
|
|
@ -18,7 +28,10 @@ class Sortable(models.Model):
|
|||
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)
|
||||
|
||||
#legacy support
|
||||
sortable_by = None
|
||||
|
||||
class Meta:
|
||||
|
|
@ -37,6 +50,17 @@ class Sortable(models.Model):
|
|||
def model_type_id(cls):
|
||||
return ContentType.objects.get_for_model(cls).id
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(Sortable, self).__init__(*args, **kwargs)
|
||||
|
||||
#Validate that model only contains at most one SortableForeignKey
|
||||
sortable_foreign_keys = []
|
||||
for field in self._meta.fields:
|
||||
if isinstance(field, SortableForeignKey):
|
||||
sortable_foreign_keys.append(field)
|
||||
if len(sortable_foreign_keys) > 1:
|
||||
raise MultipleSortableForeignKeyException(u'%s may only have one SortableForeignKey' % self)
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if not self.id:
|
||||
try:
|
||||
|
|
|
|||
0
adminsortable/static/adminsortable/css/admin.sortable.css
Executable file → Normal file
0
adminsortable/static/adminsortable/css/admin.sortable.css
Executable file → Normal file
0
adminsortable/static/adminsortable/css/admin.sortable.tabular.inline.css
Executable file → Normal file
0
adminsortable/static/adminsortable/css/admin.sortable.tabular.inline.css
Executable file → Normal file
0
adminsortable/static/adminsortable/js/admin.sortable.js
Executable file → Normal file
0
adminsortable/static/adminsortable/js/admin.sortable.js
Executable file → Normal file
0
adminsortable/static/adminsortable/js/admin.sortable.stacked.inlines.js
Executable file → Normal file
0
adminsortable/static/adminsortable/js/admin.sortable.stacked.inlines.js
Executable file → Normal file
0
adminsortable/static/adminsortable/js/admin.sortable.tabular.inlines.js
Executable file → Normal file
0
adminsortable/static/adminsortable/js/admin.sortable.tabular.inlines.js
Executable file → Normal file
0
adminsortable/static/adminsortable/js/jquery.effects.core.js
vendored
Executable file → Normal file
0
adminsortable/static/adminsortable/js/jquery.effects.core.js
vendored
Executable file → Normal file
0
adminsortable/static/adminsortable/js/jquery.effects.highlight.js
vendored
Executable file → Normal file
0
adminsortable/static/adminsortable/js/jquery.effects.highlight.js
vendored
Executable file → Normal file
0
adminsortable/static/adminsortable/js/jquery.ui.core.js
vendored
Executable file → Normal file
0
adminsortable/static/adminsortable/js/jquery.ui.core.js
vendored
Executable file → Normal file
0
adminsortable/static/adminsortable/js/jquery.ui.draggable.js
vendored
Executable file → Normal file
0
adminsortable/static/adminsortable/js/jquery.ui.draggable.js
vendored
Executable file → Normal file
0
adminsortable/static/adminsortable/js/jquery.ui.droppable.js
vendored
Executable file → Normal file
0
adminsortable/static/adminsortable/js/jquery.ui.droppable.js
vendored
Executable file → Normal file
0
adminsortable/static/adminsortable/js/jquery.ui.mouse.js
vendored
Executable file → Normal file
0
adminsortable/static/adminsortable/js/jquery.ui.mouse.js
vendored
Executable file → Normal file
0
adminsortable/static/adminsortable/js/jquery.ui.sortable.js
vendored
Executable file → Normal file
0
adminsortable/static/adminsortable/js/jquery.ui.sortable.js
vendored
Executable file → Normal file
0
adminsortable/static/adminsortable/js/jquery.ui.widget.js
vendored
Executable file → Normal file
0
adminsortable/static/adminsortable/js/jquery.ui.widget.js
vendored
Executable file → Normal file
0
adminsortable/templates/adminsortable/change_form.html
Executable file → Normal file
0
adminsortable/templates/adminsortable/change_form.html
Executable file → Normal file
0
adminsortable/templates/adminsortable/change_list.html
Executable file → Normal file
0
adminsortable/templates/adminsortable/change_list.html
Executable file → Normal file
0
adminsortable/templates/adminsortable/change_list_with_sort_link.html
Executable file → Normal file
0
adminsortable/templates/adminsortable/change_list_with_sort_link.html
Executable file → Normal file
0
adminsortable/templates/adminsortable/edit_inline/stacked.html
Executable file → Normal file
0
adminsortable/templates/adminsortable/edit_inline/stacked.html
Executable file → Normal file
0
adminsortable/templates/adminsortable/edit_inline/tabular.html
Executable file → Normal file
0
adminsortable/templates/adminsortable/edit_inline/tabular.html
Executable file → Normal file
0
adminsortable/templates/adminsortable/shared/javascript_includes.html
Executable file → Normal file
0
adminsortable/templates/adminsortable/shared/javascript_includes.html
Executable file → Normal file
0
adminsortable/templates/adminsortable/shared/list_items.html
Executable file → Normal file
0
adminsortable/templates/adminsortable/shared/list_items.html
Executable file → Normal file
0
adminsortable/templates/adminsortable/shared/nested_objects.html
Executable file → Normal file
0
adminsortable/templates/adminsortable/shared/nested_objects.html
Executable file → Normal file
0
adminsortable/templates/adminsortable/shared/object_rep.html
Executable file → Normal file
0
adminsortable/templates/adminsortable/shared/object_rep.html
Executable file → Normal file
0
adminsortable/templates/adminsortable/shared/objects.html
Executable file → Normal file
0
adminsortable/templates/adminsortable/shared/objects.html
Executable file → Normal file
0
adminsortable/templatetags/__init__.py
Executable file → Normal file
0
adminsortable/templatetags/__init__.py
Executable file → Normal file
0
adminsortable/templatetags/adminsortable_tags.py
Executable file → Normal file
0
adminsortable/templatetags/adminsortable_tags.py
Executable file → Normal file
0
adminsortable/templatetags/django_template_additions.py
Executable file → Normal file
0
adminsortable/templatetags/django_template_additions.py
Executable file → Normal file
0
sample_project/README
Executable file → Normal file
0
sample_project/README
Executable file → Normal file
0
sample_project/__init__.py
Executable file → Normal file
0
sample_project/__init__.py
Executable file → Normal file
BIN
sample_project/adminsortable.sqlite
Executable file → Normal file
BIN
sample_project/adminsortable.sqlite
Executable file → Normal file
Binary file not shown.
0
sample_project/app/__init__.py
Executable file → Normal file
0
sample_project/app/__init__.py
Executable file → Normal file
3
sample_project/app/admin.py
Executable file → Normal file
3
sample_project/app/admin.py
Executable file → Normal file
|
|
@ -1,7 +1,7 @@
|
|||
from django.contrib import admin
|
||||
|
||||
from adminsortable.admin import SortableAdmin, SortableTabularInline, SortableStackedInline
|
||||
from app.models import Category, Project, Credit, Note, Sample
|
||||
from app.models import Category, Project, Credit, Note
|
||||
|
||||
|
||||
admin.site.register(Category, SortableAdmin)
|
||||
|
|
@ -20,4 +20,3 @@ class ProjectAdmin(SortableAdmin):
|
|||
list_display = ['__unicode__', 'category']
|
||||
|
||||
admin.site.register(Project, ProjectAdmin)
|
||||
admin.site.register(Sample, SortableAdmin)
|
||||
|
|
|
|||
56
sample_project/app/fixtures/initial_data.json
Normal file
56
sample_project/app/fixtures/initial_data.json
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
[
|
||||
{
|
||||
"pk": 1,
|
||||
"model": "app.category",
|
||||
"fields": {
|
||||
"order": 1,
|
||||
"title": "Test 1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 2,
|
||||
"model": "app.category",
|
||||
"fields": {
|
||||
"order": 2,
|
||||
"title": "Test 2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 3,
|
||||
"model": "app.category",
|
||||
"fields": {
|
||||
"order": 3,
|
||||
"title": "Test 3"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 1,
|
||||
"model": "app.project",
|
||||
"fields": {
|
||||
"category": 1,
|
||||
"description": "Test",
|
||||
"order": 1,
|
||||
"title": "Test Project 1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 2,
|
||||
"model": "app.project",
|
||||
"fields": {
|
||||
"category": 1,
|
||||
"description": "Test",
|
||||
"order": 2,
|
||||
"title": "Test Project 2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 3,
|
||||
"model": "app.project",
|
||||
"fields": {
|
||||
"category": 2,
|
||||
"description": "Test",
|
||||
"order": 3,
|
||||
"title": "Test Project 3"
|
||||
}
|
||||
}
|
||||
]
|
||||
0
sample_project/app/fixtures/test_data.json
Executable file → Normal file
0
sample_project/app/fixtures/test_data.json
Executable file → Normal file
|
|
@ -1,77 +0,0 @@
|
|||
# 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 'Category'
|
||||
db.create_table('app_category', (
|
||||
('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)),
|
||||
))
|
||||
db.send_create_signal('app', ['Category'])
|
||||
|
||||
# Adding model 'Project'
|
||||
db.create_table('app_project', (
|
||||
('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', ['Project'])
|
||||
|
||||
# Adding model 'Credit'
|
||||
db.create_table('app_credit', (
|
||||
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
|
||||
('order', self.gf('django.db.models.fields.PositiveIntegerField')(default=1, db_index=True)),
|
||||
('project', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['app.Project'])),
|
||||
('first_name', self.gf('django.db.models.fields.CharField')(max_length=30)),
|
||||
('last_name', self.gf('django.db.models.fields.CharField')(max_length=30)),
|
||||
))
|
||||
db.send_create_signal('app', ['Credit'])
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
|
||||
# Deleting model 'Category'
|
||||
db.delete_table('app_category')
|
||||
|
||||
# Deleting model 'Project'
|
||||
db.delete_table('app_project')
|
||||
|
||||
# Deleting model 'Credit'
|
||||
db.delete_table('app_credit')
|
||||
|
||||
|
||||
models = {
|
||||
'app.category': {
|
||||
'Meta': {'ordering': "['order', 'id']", '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', 'id']", '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.project': {
|
||||
'Meta': {'ordering': "['order', 'id']", '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'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['app']
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
# 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 'Note'
|
||||
db.create_table('app_note', (
|
||||
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
|
||||
('order', self.gf('django.db.models.fields.PositiveIntegerField')(default=1, db_index=True)),
|
||||
('project', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['app.Project'])),
|
||||
('text', self.gf('django.db.models.fields.CharField')(max_length=100)),
|
||||
))
|
||||
db.send_create_signal('app', ['Note'])
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
|
||||
# Deleting model 'Note'
|
||||
db.delete_table('app_note')
|
||||
|
||||
|
||||
models = {
|
||||
'app.category': {
|
||||
'Meta': {'ordering': "['order', 'id']", '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', 'id']", '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', 'id']", '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', 'id']", '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'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['app']
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
# 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']
|
||||
27
sample_project/app/models.py
Executable file → Normal file
27
sample_project/app/models.py
Executable file → Normal file
|
|
@ -1,5 +1,6 @@
|
|||
from django.db import models
|
||||
|
||||
from adminsortable.fields import SortableForeignKey
|
||||
from adminsortable.models import Sortable
|
||||
|
||||
|
||||
|
|
@ -25,34 +26,16 @@ class Category(SimpleModel, Sortable):
|
|||
|
||||
|
||||
#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
|
||||
|
||||
#deprecated: shown for backward compatibility only. Reference class "Sample" for proper
|
||||
# designation of `sortable_by` as a property
|
||||
@classmethod
|
||||
def sortable_by(cls):
|
||||
return Category, 'category'
|
||||
|
||||
category = models.ForeignKey(Category)
|
||||
category = SortableForeignKey(Category)
|
||||
description = models.TextField()
|
||||
|
||||
|
||||
#a model that is sortable relative to a foreign key that is also sortable
|
||||
class Sample(SimpleModel, Sortable):
|
||||
class Meta(Sortable.Meta):
|
||||
ordering = Sortable.Meta.ordering + ['category']
|
||||
|
||||
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 Meta(Sortable.Meta):
|
||||
pass
|
||||
|
|
@ -65,7 +48,7 @@ class Credit(Sortable):
|
|||
return '%s %s' % (self.first_name, self.last_name)
|
||||
|
||||
|
||||
#registered as a stacked inline on project
|
||||
#registered as a stacked inline on `Project`
|
||||
class Note(Sortable):
|
||||
class Meta(Sortable.Meta):
|
||||
pass
|
||||
|
|
|
|||
11
sample_project/app/tests.py
Executable file → Normal file
11
sample_project/app/tests.py
Executable file → Normal file
|
|
@ -7,8 +7,14 @@ from django.db import models
|
|||
from django.test import TestCase
|
||||
from django.test.client import Client, RequestFactory
|
||||
|
||||
from models import Sortable
|
||||
from app.models import Category
|
||||
from adminsortable.fields import SortableForeignKey
|
||||
from adminsortable.models import Sortable, MultipleSortableForeignKeyException
|
||||
from app.models import Category, Credit, Note
|
||||
|
||||
|
||||
class BadSortableModel(models.Model):
|
||||
note = SortableForeignKey(Note)
|
||||
credit = SortableForeignKey(Credit)
|
||||
|
||||
|
||||
class TestSortableModel(Sortable):
|
||||
|
|
@ -19,7 +25,6 @@ class TestSortableModel(Sortable):
|
|||
|
||||
|
||||
class SortableTestCase(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.client = Client()
|
||||
self.factory = RequestFactory()
|
||||
|
|
|
|||
0
sample_project/appmedia/BeautifulSoup.py
Executable file → Normal file
0
sample_project/appmedia/BeautifulSoup.py
Executable file → Normal file
0
sample_project/appmedia/__init__.py
Executable file → Normal file
0
sample_project/appmedia/__init__.py
Executable file → Normal file
0
sample_project/appmedia/api.py
Executable file → Normal file
0
sample_project/appmedia/api.py
Executable file → Normal file
0
sample_project/appmedia/management/__init__.py
Executable file → Normal file
0
sample_project/appmedia/management/__init__.py
Executable file → Normal file
0
sample_project/appmedia/management/commands/__init__.py
Executable file → Normal file
0
sample_project/appmedia/management/commands/__init__.py
Executable file → Normal file
0
sample_project/appmedia/management/commands/buildmedia.py
Executable file → Normal file
0
sample_project/appmedia/management/commands/buildmedia.py
Executable file → Normal file
0
sample_project/appmedia/management/commands/symlinkmedia.py
Executable file → Normal file
0
sample_project/appmedia/management/commands/symlinkmedia.py
Executable file → Normal file
0
sample_project/appmedia/middleware.py
Executable file → Normal file
0
sample_project/appmedia/middleware.py
Executable file → Normal file
0
sample_project/appmedia/models.py
Executable file → Normal file
0
sample_project/appmedia/models.py
Executable file → Normal file
0
sample_project/appmedia/urls.py
Executable file → Normal file
0
sample_project/appmedia/urls.py
Executable file → Normal file
0
sample_project/appmedia/views.py
Executable file → Normal file
0
sample_project/appmedia/views.py
Executable file → Normal file
0
sample_project/manage.py
Executable file → Normal file
0
sample_project/manage.py
Executable file → Normal file
0
sample_project/settings.py
Executable file → Normal file
0
sample_project/settings.py
Executable file → Normal file
0
sample_project/static/adminsortable/css/admin.sortable.css
Executable file → Normal file
0
sample_project/static/adminsortable/css/admin.sortable.css
Executable file → Normal file
0
sample_project/static/adminsortable/css/admin.sortable.tabular.inline.css
Executable file → Normal file
0
sample_project/static/adminsortable/css/admin.sortable.tabular.inline.css
Executable file → Normal file
0
sample_project/static/adminsortable/js/admin.sortable.js
Executable file → Normal file
0
sample_project/static/adminsortable/js/admin.sortable.js
Executable file → Normal file
0
sample_project/static/adminsortable/js/admin.sortable.stacked.inlines.js
Executable file → Normal file
0
sample_project/static/adminsortable/js/admin.sortable.stacked.inlines.js
Executable file → Normal file
0
sample_project/static/adminsortable/js/admin.sortable.tabular.inlines.js
Executable file → Normal file
0
sample_project/static/adminsortable/js/admin.sortable.tabular.inlines.js
Executable file → Normal file
0
sample_project/static/adminsortable/js/jquery.effects.core.js
vendored
Executable file → Normal file
0
sample_project/static/adminsortable/js/jquery.effects.core.js
vendored
Executable file → Normal file
0
sample_project/static/adminsortable/js/jquery.effects.highlight.js
vendored
Executable file → Normal file
0
sample_project/static/adminsortable/js/jquery.effects.highlight.js
vendored
Executable file → Normal file
0
sample_project/static/adminsortable/js/jquery.ui.core.js
vendored
Executable file → Normal file
0
sample_project/static/adminsortable/js/jquery.ui.core.js
vendored
Executable file → Normal file
0
sample_project/static/adminsortable/js/jquery.ui.draggable.js
vendored
Executable file → Normal file
0
sample_project/static/adminsortable/js/jquery.ui.draggable.js
vendored
Executable file → Normal file
0
sample_project/static/adminsortable/js/jquery.ui.droppable.js
vendored
Executable file → Normal file
0
sample_project/static/adminsortable/js/jquery.ui.droppable.js
vendored
Executable file → Normal file
0
sample_project/static/adminsortable/js/jquery.ui.mouse.js
vendored
Executable file → Normal file
0
sample_project/static/adminsortable/js/jquery.ui.mouse.js
vendored
Executable file → Normal file
0
sample_project/static/adminsortable/js/jquery.ui.sortable.js
vendored
Executable file → Normal file
0
sample_project/static/adminsortable/js/jquery.ui.sortable.js
vendored
Executable file → Normal file
0
sample_project/static/adminsortable/js/jquery.ui.widget.js
vendored
Executable file → Normal file
0
sample_project/static/adminsortable/js/jquery.ui.widget.js
vendored
Executable file → Normal file
0
sample_project/templates/index.html
Executable file → Normal file
0
sample_project/templates/index.html
Executable file → Normal file
0
sample_project/urls.py
Executable file → Normal file
0
sample_project/urls.py
Executable file → Normal file
0
setup.py
Executable file → Normal file
0
setup.py
Executable file → Normal file
Loading…
Reference in a new issue