From 6ecd0829582501df2c88a89264648075970a4374 Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Wed, 8 Oct 2014 15:28:10 +0100 Subject: [PATCH 1/3] Added last_revision_created_at to Page --- .../0007_page_latest_revision_created_at.py | 20 +++ ...008_populate_latest_revision_created_at.py | 26 ++++ wagtail/wagtailcore/models.py | 9 +- ...d_field_page_latest_revision_created_at.py | 116 +++++++++++++++++ ...010_populate_latest_revision_created_at.py | 118 ++++++++++++++++++ 5 files changed, 288 insertions(+), 1 deletion(-) create mode 100644 wagtail/wagtailcore/migrations/0007_page_latest_revision_created_at.py create mode 100644 wagtail/wagtailcore/migrations/0008_populate_latest_revision_created_at.py create mode 100644 wagtail/wagtailcore/south_migrations/0009_auto__add_field_page_latest_revision_created_at.py create mode 100644 wagtail/wagtailcore/south_migrations/0010_populate_latest_revision_created_at.py diff --git a/wagtail/wagtailcore/migrations/0007_page_latest_revision_created_at.py b/wagtail/wagtailcore/migrations/0007_page_latest_revision_created_at.py new file mode 100644 index 000000000..38e51d376 --- /dev/null +++ b/wagtail/wagtailcore/migrations/0007_page_latest_revision_created_at.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('wagtailcore', '0006_add_lock_page_permission'), + ] + + operations = [ + migrations.AddField( + model_name='page', + name='latest_revision_created_at', + field=models.DateTimeField(editable=False, null=True), + preserve_default=True, + ), + ] diff --git a/wagtail/wagtailcore/migrations/0008_populate_latest_revision_created_at.py b/wagtail/wagtailcore/migrations/0008_populate_latest_revision_created_at.py new file mode 100644 index 000000000..8ce90ffbe --- /dev/null +++ b/wagtail/wagtailcore/migrations/0008_populate_latest_revision_created_at.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +def populate_latest_revision_created_at(apps, schema_editor): + Page = apps.get_model('wagtailcore.Page') + + for page in Page.objects.all(): + latest_revision = page.revisions.order_by('-created_at').first() + + if latest_revision is not None: + page.latest_revision_created_at = latest_revision.created_at + page.save(update_fields=['latest_revision_created_at']) + + +class Migration(migrations.Migration): + + dependencies = [ + ('wagtailcore', '0007_page_latest_revision_created_at'), + ] + + operations = [ + migrations.RunPython(populate_latest_revision_created_at), + ] diff --git a/wagtail/wagtailcore/models.py b/wagtail/wagtailcore/models.py index c67ddc76f..a4d0bed92 100644 --- a/wagtail/wagtailcore/models.py +++ b/wagtail/wagtailcore/models.py @@ -272,6 +272,8 @@ class Page(six.with_metaclass(PageBase, MP_Node, ClusterableModel, index.Indexed locked = models.BooleanField(default=False, editable=False) + latest_revision_created_at = models.DateTimeField(null=True, editable=False) + search_fields = ( index.SearchField('title', partial_match=True, boost=2), index.FilterField('id'), @@ -410,13 +412,18 @@ class Page(six.with_metaclass(PageBase, MP_Node, ClusterableModel, index.Indexed raise Http404 def save_revision(self, user=None, submitted_for_moderation=False, approved_go_live_at=None): - return self.revisions.create( + revision = self.revisions.create( content_json=self.to_json(), user=user, submitted_for_moderation=submitted_for_moderation, approved_go_live_at=approved_go_live_at, ) + self.latest_revision_created_at = revision.created_at + self.save(update_fields=['latest_revision_created_at']) + + return revision + def get_latest_revision(self): return self.revisions.order_by('-created_at').first() diff --git a/wagtail/wagtailcore/south_migrations/0009_auto__add_field_page_latest_revision_created_at.py b/wagtail/wagtailcore/south_migrations/0009_auto__add_field_page_latest_revision_created_at.py new file mode 100644 index 000000000..244323716 --- /dev/null +++ b/wagtail/wagtailcore/south_migrations/0009_auto__add_field_page_latest_revision_created_at.py @@ -0,0 +1,116 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from south.utils import datetime_utils as datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding field 'Page.latest_revision_created_at' + db.add_column('wagtailcore_page', 'latest_revision_created_at', + self.gf('django.db.models.fields.DateTimeField')(null=True), + keep_default=False) + + + def backwards(self, orm): + # Deleting field 'Page.latest_revision_created_at' + db.delete_column('wagtailcore_page', 'latest_revision_created_at') + + + models = { + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'user_set'", 'blank': 'True', 'to': "orm['auth.Group']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'user_set'", 'blank': 'True', 'to': "orm['auth.Permission']"}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'wagtailcore.grouppagepermission': { + 'Meta': {'unique_together': "(('group', 'page', 'permission_type'),)", 'object_name': 'GroupPagePermission'}, + 'group': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'page_permissions'", 'to': "orm['auth.Group']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'page': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'group_permissions'", 'to': "orm['wagtailcore.Page']"}), + 'permission_type': ('django.db.models.fields.CharField', [], {'max_length': '20'}) + }, + 'wagtailcore.page': { + 'Meta': {'object_name': 'Page'}, + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'pages'", 'to': "orm['contenttypes.ContentType']"}), + 'depth': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'expire_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'expired': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'go_live_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'has_unpublished_changes': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'latest_revision_created_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), + 'live': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'locked': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'numchild': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'owner': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'owned_pages'", 'null': 'True', 'to': "orm['auth.User']"}), + 'path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'search_description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'seo_title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'show_in_menus': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'url_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}) + }, + 'wagtailcore.pagerevision': { + 'Meta': {'object_name': 'PageRevision'}, + 'approved_go_live_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'content_json': ('django.db.models.fields.TextField', [], {}), + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'page': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['wagtailcore.Page']"}), + 'submitted_for_moderation': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}) + }, + 'wagtailcore.pageviewrestriction': { + 'Meta': {'object_name': 'PageViewRestriction'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'page': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'view_restrictions'", 'to': "orm['wagtailcore.Page']"}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '255'}) + }, + 'wagtailcore.site': { + 'Meta': {'unique_together': "(('hostname', 'port'),)", 'object_name': 'Site'}, + 'hostname': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_default_site': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'port': ('django.db.models.fields.IntegerField', [], {'default': '80'}), + 'root_page': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'sites_rooted_here'", 'to': "orm['wagtailcore.Page']"}) + } + } + + complete_apps = ['wagtailcore'] \ No newline at end of file diff --git a/wagtail/wagtailcore/south_migrations/0010_populate_latest_revision_created_at.py b/wagtail/wagtailcore/south_migrations/0010_populate_latest_revision_created_at.py new file mode 100644 index 000000000..e1854dea0 --- /dev/null +++ b/wagtail/wagtailcore/south_migrations/0010_populate_latest_revision_created_at.py @@ -0,0 +1,118 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from south.utils import datetime_utils as datetime +from south.db import db +from south.v2 import DataMigration +from django.db import models + + +class Migration(DataMigration): + + def forwards(self, orm): + Page = orm['wagtailcore.Page'] + + for page in Page.objects.all(): + latest_revision = page.revisions.order_by('-created_at').first() + + if latest_revision is not None: + page.latest_revision_created_at = latest_revision.created_at + page.save(update_fields=['latest_revision_created_at']) + + def backwards(self, orm): + "Write your backwards methods here." + + models = { + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'user_set'", 'blank': 'True', 'to': "orm['auth.Group']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'user_set'", 'blank': 'True', 'to': "orm['auth.Permission']"}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'wagtailcore.grouppagepermission': { + 'Meta': {'unique_together': "(('group', 'page', 'permission_type'),)", 'object_name': 'GroupPagePermission'}, + 'group': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'page_permissions'", 'to': "orm['auth.Group']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'page': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'group_permissions'", 'to': "orm['wagtailcore.Page']"}), + 'permission_type': ('django.db.models.fields.CharField', [], {'max_length': '20'}) + }, + 'wagtailcore.page': { + 'Meta': {'object_name': 'Page'}, + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'pages'", 'to': "orm['contenttypes.ContentType']"}), + 'depth': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'expire_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'expired': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'go_live_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'has_unpublished_changes': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'latest_revision_created_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), + 'live': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'locked': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'numchild': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'owner': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'owned_pages'", 'null': 'True', 'to': "orm['auth.User']"}), + 'path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'search_description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'seo_title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'show_in_menus': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'url_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}) + }, + 'wagtailcore.pagerevision': { + 'Meta': {'object_name': 'PageRevision'}, + 'approved_go_live_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'content_json': ('django.db.models.fields.TextField', [], {}), + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'page': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['wagtailcore.Page']"}), + 'submitted_for_moderation': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}) + }, + 'wagtailcore.pageviewrestriction': { + 'Meta': {'object_name': 'PageViewRestriction'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'page': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'view_restrictions'", 'to': "orm['wagtailcore.Page']"}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '255'}) + }, + 'wagtailcore.site': { + 'Meta': {'unique_together': "(('hostname', 'port'),)", 'object_name': 'Site'}, + 'hostname': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_default_site': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'port': ('django.db.models.fields.IntegerField', [], {'default': '80'}), + 'root_page': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'sites_rooted_here'", 'to': "orm['wagtailcore.Page']"}) + } + } + + complete_apps = ['wagtailcore'] + symmetrical = True From 19cb2c57310641721b41892017031e539c588cf3 Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Wed, 8 Oct 2014 16:13:55 +0100 Subject: [PATCH 2/3] UI for ordering by latest revision --- .../templates/wagtailadmin/pages/list.html | 15 ++++++++++++++- wagtail/wagtailadmin/views/pages.py | 12 ++++++++---- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/wagtail/wagtailadmin/templates/wagtailadmin/pages/list.html b/wagtail/wagtailadmin/templates/wagtailadmin/pages/list.html index 1a4929228..13899c70f 100644 --- a/wagtail/wagtailadmin/templates/wagtailadmin/pages/list.html +++ b/wagtail/wagtailadmin/templates/wagtailadmin/pages/list.html @@ -10,6 +10,7 @@ {% endif %} + {% if moving or choosing %} @@ -21,6 +22,7 @@ {% if show_parent %} {% trans 'Parent' %} {% endif %} + {% trans 'Updated' %} {% trans 'Type' %} {% trans 'Status' %} @@ -96,6 +98,7 @@ {% endif %} +
{{ parent_page.latest_revision_created_at|timesince }}
{{ parent_page.content_type.model_class.get_verbose_name }} {% if not choosing and not moving and parent_page.live and not parent_page.is_root and 'view_live' not in hide_actions|default:'' %} @@ -129,8 +132,17 @@ {% endif %} {% if show_parent %} - Parent + {% trans 'Parent' %} {% endif %} + + {% if sortable %} + + {% trans 'Updated' %} + + {% else %} + {% trans 'Updated' %} + {% endif %} + {% if sortable %} @@ -230,6 +242,7 @@ {% endwith %} {% endif %} +
{{ page.latest_revision_created_at|timesince }}
{{ page.content_type.model_class.get_verbose_name }} {% if not choosing and not moving and page.live and 'view_live' not in hide_actions|default:'' %} diff --git a/wagtail/wagtailadmin/views/pages.py b/wagtail/wagtailadmin/views/pages.py index 9fd1c7186..d0f7f7d29 100644 --- a/wagtail/wagtailadmin/views/pages.py +++ b/wagtail/wagtailadmin/views/pages.py @@ -12,6 +12,7 @@ from django.utils.translation import ugettext as _ from django.utils.http import is_safe_url from django.views.decorators.http import require_GET, require_POST from django.views.decorators.vary import vary_on_headers +from django.db.models import Count from wagtail.wagtailadmin.edit_handlers import TabbedInterface, ObjectList from wagtail.wagtailadmin.forms import SearchForm, CopyForm @@ -38,13 +39,16 @@ def index(request, parent_page_id=None): pages = parent_page.get_children().prefetch_related('content_type') # Get page ordering - ordering = request.GET.get('ordering', 'title') - if ordering not in ['title', '-title', 'content_type', '-content_type', 'live', '-live', 'ord']: - ordering = 'title' + ordering = request.GET.get('ordering', '-latest_revision_created_at') + if ordering not in ['title', '-title', 'content_type', '-content_type', 'live', '-live', 'latest_revision_created_at', '-latest_revision_created_at', 'ord']: + ordering = '-latest_revision_created_at' # Pagination if ordering != 'ord': - pages = pages.order_by(ordering) + ordering_no_minus = ordering + if ordering_no_minus.startswith('-'): + ordering_no_minus = ordering[1:] + pages = pages.order_by(ordering).annotate(null_position=Count(ordering_no_minus)).order_by('-null_position', ordering) p = request.GET.get('p', 1) paginator = Paginator(pages, 50) From d1d5e68ed440f91d1d993c92724fe725315aae08 Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Wed, 8 Oct 2014 18:38:16 +0100 Subject: [PATCH 3/3] Fixed test --- wagtail/wagtailadmin/tests/test_pages_views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wagtail/wagtailadmin/tests/test_pages_views.py b/wagtail/wagtailadmin/tests/test_pages_views.py index 630ce6482..2145e42f9 100644 --- a/wagtail/wagtailadmin/tests/test_pages_views.py +++ b/wagtail/wagtailadmin/tests/test_pages_views.py @@ -69,7 +69,7 @@ class TestPageExplorer(TestCase, WagtailTestUtils): response = self.client.get(reverse('wagtailadmin_explore_root'), {'ordering': 'invalid_order'}) self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, 'wagtailadmin/pages/index.html') - self.assertEqual(response.context['ordering'], 'title') + self.assertEqual(response.context['ordering'], '-latest_revision_created_at') def test_reordering(self): response = self.client.get(reverse('wagtailadmin_explore_root'), {'ordering': 'ord'})