diff --git a/wagtail/utils/compat.py b/wagtail/utils/compat.py index e3d47fddb..2f8fad692 100644 --- a/wagtail/utils/compat.py +++ b/wagtail/utils/compat.py @@ -12,6 +12,15 @@ def get_related_model(rel): return rel.model +def get_related_parent_model(rel): + # In Django 1.7 and under, the parent model is accessed by doing: rel.parent_model + # This was renamed in Django 1.8 to rel.model. + if django.VERSION >= (1, 8): + return rel.model + else: + return rel.parent_model + + def render_to_string(template_name, context=None, request=None, **kwargs): if django.VERSION >= (1, 8): return loader.render_to_string( diff --git a/wagtail/wagtailadmin/edit_handlers.py b/wagtail/wagtailadmin/edit_handlers.py index 78d842269..9dcce9ddc 100644 --- a/wagtail/wagtailadmin/edit_handlers.py +++ b/wagtail/wagtailadmin/edit_handlers.py @@ -19,7 +19,7 @@ from taggit.managers import TaggableManager from wagtail.wagtailadmin import widgets from wagtail.wagtailcore.models import Page from wagtail.wagtailcore.utils import camelcase_to_underscore, resolve_model_string -from wagtail.utils.compat import get_related_model +from wagtail.utils.compat import get_related_model, get_related_parent_model # Form field properties to override whenever we encounter a model field @@ -525,7 +525,7 @@ class BaseChooserPanel(BaseFieldPanel): def get_chosen_item(self): field = self.instance._meta.get_field(self.field_name) - related_model = get_related_model(field.related) + related_model = get_related_parent_model(field.related) try: return getattr(self.instance, self.field_name) except related_model.DoesNotExist: diff --git a/wagtail/wagtailadmin/templates/wagtailadmin/chooser/_search_results.html b/wagtail/wagtailadmin/templates/wagtailadmin/chooser/_search_results.html index 9c624c00c..42f1ed631 100644 --- a/wagtail/wagtailadmin/templates/wagtailadmin/chooser/_search_results.html +++ b/wagtail/wagtailadmin/templates/wagtailadmin/chooser/_search_results.html @@ -1,7 +1,7 @@ -{% load i18n %} +{% load i18n wagtailadmin_tags %}

- {% blocktrans count counter=pages|length %} + {% blocktrans count counter=pages.paginator.count %} There is one match {% plural %} There are {{ counter }} matches @@ -10,4 +10,7 @@ {% if pages %} {% include "wagtailadmin/pages/listing/_list_choose.html" with show_parent=1 pages=pages parent_page=parent_page %} + + {% url 'wagtailadmin_choose_page_search' as pagination_base_url %} + {% paginate pages base_url=pagination_base_url classnames="navigate-pages" %} {% endif %} diff --git a/wagtail/wagtailadmin/templates/wagtailadmin/chooser/browse.js b/wagtail/wagtailadmin/templates/wagtailadmin/chooser/browse.js index 9566541b7..e6e2c8bc6 100644 --- a/wagtail/wagtailadmin/templates/wagtailadmin/chooser/browse.js +++ b/wagtail/wagtailadmin/templates/wagtailadmin/chooser/browse.js @@ -52,6 +52,12 @@ function(modal) { return false; }); + /* pagination links within search results should be AJAX-fetched + and the result loaded into .page-results (and ajaxified) */ + $('.page-results a.navigate-pages', modal.body).click(function() { + $('.page-results', modal.body).load(this.href, ajaxifySearchResults); + return false; + }); } /* diff --git a/wagtail/wagtailadmin/tests/test_edit_handlers.py b/wagtail/wagtailadmin/tests/test_edit_handlers.py index 5049910b6..c37569258 100644 --- a/wagtail/wagtailadmin/tests/test_edit_handlers.py +++ b/wagtail/wagtailadmin/tests/test_edit_handlers.py @@ -382,6 +382,16 @@ class TestPageChooserPanel(TestCase): 'Edit this page' % self.christmas_page.id, result) + def test_render_as_empty_field(self): + test_instance = PageChooserModel() + form = self.PageChooserForm(instance=test_instance) + page_chooser_panel = self.MyPageChooserPanel(instance=test_instance, form=form) + result = page_chooser_panel.render_as_field() + + self.assertIn('

help text

', result) + self.assertIn('', result) + self.assertIn('Choose a page', result) + def test_render_error(self): form = self.PageChooserForm({'page': ''}, instance=self.test_instance) self.assertFalse(form.is_valid()) diff --git a/wagtail/wagtailadmin/views/chooser.py b/wagtail/wagtailadmin/views/chooser.py index f14533329..15ffa5bfd 100644 --- a/wagtail/wagtailadmin/views/chooser.py +++ b/wagtail/wagtailadmin/views/chooser.py @@ -116,20 +116,20 @@ def search(request, parent_page_id=None): depth=1 # never include root ) pages = filter_page_type(pages, desired_classes) - pages = pages.search(search_form.cleaned_data['q'], fields=['title'])[:10] + pages = pages.search(search_form.cleaned_data['q'], fields=['title']) else: pages = Page.objects.none() - shown_pages = [] + paginator, pages = paginate(request, pages, per_page=25) + for page in pages: page.can_choose = True - shown_pages.append(page) return render( request, 'wagtailadmin/chooser/_search_results.html', shared_context(request, { 'searchform': search_form, - 'pages': shown_pages, + 'pages': pages, 'page_type_string': page_type_string, }) ) diff --git a/wagtail/wagtailcore/migrations/0020_add_index_on_page_first_published_at.py b/wagtail/wagtailcore/migrations/0020_add_index_on_page_first_published_at.py new file mode 100644 index 000000000..87ad61fb3 --- /dev/null +++ b/wagtail/wagtailcore/migrations/0020_add_index_on_page_first_published_at.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('wagtailcore', '0019_verbose_names_cleanup'), + ] + + operations = [ + migrations.AlterField( + model_name='page', + name='first_published_at', + field=models.DateTimeField(editable=False, null=True, verbose_name='First published at', db_index=True), + ), + ] diff --git a/wagtail/wagtailcore/models.py b/wagtail/wagtailcore/models.py index e535bd436..ccdafbcab 100644 --- a/wagtail/wagtailcore/models.py +++ b/wagtail/wagtailcore/models.py @@ -239,7 +239,7 @@ class Page(six.with_metaclass(PageBase, MP_Node, ClusterableModel, index.Indexed locked = models.BooleanField(verbose_name=_('Locked'), default=False, editable=False) - first_published_at = models.DateTimeField(verbose_name=_('First published at'), null=True, editable=False) + first_published_at = models.DateTimeField(verbose_name=_('First published at'), null=True, editable=False, db_index=True) latest_revision_created_at = models.DateTimeField(verbose_name=_('Latest revision created at'), null=True, editable=False) search_fields = ( diff --git a/wagtail/wagtailsnippets/tests.py b/wagtail/wagtailsnippets/tests.py index fa9d68b12..b3551939f 100644 --- a/wagtail/wagtailsnippets/tests.py +++ b/wagtail/wagtailsnippets/tests.py @@ -255,10 +255,10 @@ class TestSnippetChooserPanel(TestCase): test_snippet = model.objects.create( advert=Advert.objects.create(text=self.advert_text)) - edit_handler_class = get_snippet_edit_handler(model) - form_class = edit_handler_class.get_form_class(model) - form = form_class(instance=test_snippet) - edit_handler = edit_handler_class(instance=test_snippet, form=form) + self.edit_handler_class = get_snippet_edit_handler(model) + self.form_class = self.edit_handler_class.get_form_class(model) + form = self.form_class(instance=test_snippet) + edit_handler = self.edit_handler_class(instance=test_snippet, form=form) self.snippet_chooser_panel = [ panel for panel in edit_handler.children @@ -274,6 +274,19 @@ class TestSnippetChooserPanel(TestCase): self.assertIn("Choose advert", field_html) self.assertIn("Choose another advert", field_html) + def test_render_as_empty_field(self): + test_snippet = SnippetChooserModel() + form = self.form_class(instance=test_snippet) + edit_handler = self.edit_handler_class(instance=test_snippet, form=form) + + snippet_chooser_panel = [ + panel for panel in edit_handler.children + if getattr(panel, 'field_name', None) == 'advert'][0] + + field_html = snippet_chooser_panel.render_as_field() + self.assertIn("Choose advert", field_html) + self.assertIn("Choose another advert", field_html) + def test_render_js(self): self.assertIn('createSnippetChooser("id_advert", "tests/advert");', self.snippet_chooser_panel.render_as_field())