Adding files to repo.
This commit is contained in:
Binary file not shown.
@@ -0,0 +1,18 @@
|
||||
from django.contrib import admin
|
||||
|
||||
from adminsortable.admin import SortableAdmin, SortableTabularInline
|
||||
from app.models import Category, Project, Credit
|
||||
|
||||
|
||||
admin.site.register(Category, SortableAdmin)
|
||||
|
||||
|
||||
class CreditInline(SortableTabularInline):
|
||||
model = Credit
|
||||
|
||||
|
||||
class ProjectAdmin(SortableAdmin):
|
||||
inlines = [CreditInline]
|
||||
list_display = ['__unicode__', 'category']
|
||||
|
||||
admin.site.register(Project, ProjectAdmin)
|
||||
Binary file not shown.
@@ -0,0 +1,136 @@
|
||||
[
|
||||
{
|
||||
"pk": 1,
|
||||
"model": "app.category",
|
||||
"fields": {
|
||||
"order": 2,
|
||||
"title": "Category 1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 2,
|
||||
"model": "app.category",
|
||||
"fields": {
|
||||
"order": 1,
|
||||
"title": "Category 2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 3,
|
||||
"model": "app.category",
|
||||
"fields": {
|
||||
"order": 3,
|
||||
"title": "Category 3"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 1,
|
||||
"model": "app.project",
|
||||
"fields": {
|
||||
"category": 1,
|
||||
"description": "Sample category 1",
|
||||
"order": 1,
|
||||
"title": "Sample Project 1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 2,
|
||||
"model": "app.project",
|
||||
"fields": {
|
||||
"category": 1,
|
||||
"description": "Another sample project.",
|
||||
"order": 2,
|
||||
"title": "Sample Project 2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 3,
|
||||
"model": "app.project",
|
||||
"fields": {
|
||||
"category": 3,
|
||||
"description": "Yest another sample project.",
|
||||
"order": 3,
|
||||
"title": "Sample Project 3"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 1,
|
||||
"model": "app.credit",
|
||||
"fields": {
|
||||
"project": 1,
|
||||
"first_name": "Bob",
|
||||
"last_name": "Smith",
|
||||
"order": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 2,
|
||||
"model": "app.credit",
|
||||
"fields": {
|
||||
"project": 1,
|
||||
"first_name": "Sally",
|
||||
"last_name": "Smith",
|
||||
"order": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 3,
|
||||
"model": "app.credit",
|
||||
"fields": {
|
||||
"project": 1,
|
||||
"first_name": "Johnny",
|
||||
"last_name": "Smith",
|
||||
"order": 3
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 4,
|
||||
"model": "app.credit",
|
||||
"fields": {
|
||||
"project": 3,
|
||||
"first_name": "Sally Ann",
|
||||
"last_name": "Smith",
|
||||
"order": 4
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 5,
|
||||
"model": "app.credit",
|
||||
"fields": {
|
||||
"project": 3,
|
||||
"first_name": "George",
|
||||
"last_name": "Smith",
|
||||
"order": 5
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 6,
|
||||
"model": "app.credit",
|
||||
"fields": {
|
||||
"project": 2,
|
||||
"first_name": "Bob",
|
||||
"last_name": "Smith",
|
||||
"order": 6
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 7,
|
||||
"model": "app.credit",
|
||||
"fields": {
|
||||
"project": 2,
|
||||
"first_name": "George",
|
||||
"last_name": "Smith",
|
||||
"order": 7
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 8,
|
||||
"model": "app.credit",
|
||||
"fields": {
|
||||
"project": 2,
|
||||
"first_name": "Sally",
|
||||
"last_name": "Smith",
|
||||
"order": 8
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,77 @@
|
||||
# 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']
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,48 @@
|
||||
from django.db import models
|
||||
|
||||
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'
|
||||
|
||||
|
||||
#a model that is sortable relative to a foreign key that is also sortable
|
||||
class Project(SimpleModel, Sortable):
|
||||
class Meta(Sortable.Meta):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def sortable_by(cls):
|
||||
return Category, 'category'
|
||||
|
||||
category = models.ForeignKey(Category)
|
||||
description = models.TextField()
|
||||
|
||||
|
||||
#registered as an inline on project
|
||||
class Credit(Sortable):
|
||||
project = models.ForeignKey(Project)
|
||||
first_name = models.CharField(max_length=30)
|
||||
last_name = models.CharField(max_length=30)
|
||||
|
||||
def __unicode__(self):
|
||||
return '%s %s' % (self.first_name, self.last_name)
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,139 @@
|
||||
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
|
||||
|
||||
from models import Sortable
|
||||
from app.models import Category
|
||||
|
||||
|
||||
class TestSortableModel(Sortable):
|
||||
title = models.CharField(max_length=100)
|
||||
|
||||
def __unicode__(self):
|
||||
return self.title
|
||||
|
||||
|
||||
class SortableTestCase(TestCase):
|
||||
|
||||
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()
|
||||
|
||||
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.
|
||||
"""
|
||||
category = self.create_category()
|
||||
self.assertFalse(Category.is_sortable(),
|
||||
'Category only has one record. It should not be sortable.')
|
||||
|
||||
def test_is_sortable(self):
|
||||
category1 = self.create_category()
|
||||
category2 = self.create_category(title='Category 2')
|
||||
self.assertTrue(Category.is_sortable(),
|
||||
'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, httplib.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 reverse('admin:admin_do_sorting', args=(),
|
||||
kwargs={'model_type_id' : 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(reverse('admin:admin_sort'))
|
||||
self.assertEqual(response.status_code, httplib.OK, u'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,
|
||||
u'adminsortable/change_list.html was not rendered')
|
||||
self.assertTrue('adminsortable/shared/javascript_includes.html' in template_names,
|
||||
u'JavaScript includes for adminsortable change list were 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)
|
||||
self.assertFalse(content.get('objects_sorted'), u'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)
|
||||
self.assertTrue(content.get('objects_sorted'), u'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, u'First category returned should have order == 1')
|
||||
self.assertEqual(cat1.pk, 3, u'Category ID 3 should have been first in queryset')
|
||||
|
||||
self.assertEqual(cat2.order, 2, u'Second category returned should have order == 2')
|
||||
self.assertEqual(cat2.pk, 2, u'Category ID 2 should have been second in queryset')
|
||||
|
||||
self.assertEqual(cat3.order, 3, u'Third category returned should have order == 3')
|
||||
self.assertEqual(cat3.pk, 1, u'Category ID 1 should have been third in queryset')
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user