From 547c29faf5d5883ddb19eff351d2121167f88279 Mon Sep 17 00:00:00 2001 From: Matt Westcott Date: Wed, 4 Feb 2015 15:46:32 +0000 Subject: [PATCH 01/40] Deprecate the base_model parameter on InlinePanel - fixes #405 --- docs/core_components/form_builder.rst | 2 +- docs/core_components/pages/editing_api.rst | 12 +++-- docs/core_components/snippets.rst | 2 +- runtests.py | 1 + wagtail/tests/models.py | 10 ++-- wagtail/tests/utils.py | 16 +++++++ wagtail/wagtailadmin/edit_handlers.py | 30 +++++++++--- .../wagtailadmin/tests/test_edit_handlers.py | 46 +++++++++++++++++-- 8 files changed, 97 insertions(+), 22 deletions(-) diff --git a/docs/core_components/form_builder.rst b/docs/core_components/form_builder.rst index 65ed639bf..a98284d35 100644 --- a/docs/core_components/form_builder.rst +++ b/docs/core_components/form_builder.rst @@ -36,7 +36,7 @@ Within the models.py of one of your apps, create a model that extends wagtailfor FormPage.content_panels = [ FieldPanel('title', classname="full title"), FieldPanel('intro', classname="full"), - InlinePanel(FormPage, 'form_fields', label="Form fields"), + InlinePanel('form_fields', label="Form fields"), FieldPanel('thank_you_text', classname="full"), MultiFieldPanel([ FieldPanel('to_address', classname="full"), diff --git a/docs/core_components/pages/editing_api.rst b/docs/core_components/pages/editing_api.rst index 2087f8c87..7cf4a7054 100644 --- a/docs/core_components/pages/editing_api.rst +++ b/docs/core_components/pages/editing_api.rst @@ -31,7 +31,7 @@ There are four basic types of panels: ``MultiFieldPanel( children, heading="", classname=None )`` This panel condenses several ``FieldPanel`` s or choosers, from a list or tuple, under a single ``heading`` string. - ``InlinePanel( base_model, relation_name, panels=None, classname=None, label='', help_text='' )`` + ``InlinePanel( relation_name, panels=None, classname=None, label='', help_text='' )`` This panel allows for the creation of a "cluster" of related objects over a join to a separate model, such as a list of related links or slides to an image carousel. This is a very powerful, but tricky feature which will take some space to cover, so we'll skip over it for now. For a full explanation on the usage of ``InlinePanel``, see :ref:`inline_panels`. ``FieldRowPanel( children, classname=None)`` @@ -354,16 +354,20 @@ Let's look at the example of adding related links to a ``Page``-derived model. W BookPage.content_panels = [ # ... - InlinePanel( BookPage, 'related_links', label="Related Links" ), + InlinePanel( 'related_links', label="Related Links" ), ] The ``RelatedLink`` class is a vanilla Django abstract model. The ``BookPageRelatedLinks`` model extends it with capability for being ordered in the Wagtail interface via the ``Orderable`` class as well as adding a ``page`` property which links the model to the ``BookPage`` model we're adding the related links objects to. Finally, in the panel definitions for ``BookPage``, we'll add an ``InlinePanel`` to provide an interface for it all. Let's look again at the parameters that ``InlinePanel`` accepts: .. code-block:: python - InlinePanel( base_model, relation_name, panels=None, label='', help_text='' ) + InlinePanel( relation_name, panels=None, label='', help_text='' ) -``base_model`` is the model you're extending with the cluster. The ``relation_name`` is the ``related_name`` label given to the cluster's ``ParentalKey`` relation. You can add the ``panels`` manually or make them part of the cluster model. Finally, ``label`` and ``help_text`` provide a heading and caption, respectively, for the Wagtail editor. +The ``relation_name`` is the ``related_name`` label given to the cluster's ``ParentalKey`` relation. You can add the ``panels`` manually or make them part of the cluster model. Finally, ``label`` and ``help_text`` provide a heading and caption, respectively, for the Wagtail editor. + +.. versionchanged:: 0.9 + + In previous versions, it was necessary to pass the base model as the first parameter to ``InlinePanel``; this is no longer required. For another example of using model clusters, see :ref:`tagging` diff --git a/docs/core_components/snippets.rst b/docs/core_components/snippets.rst index 33d20bdc4..e323bdb68 100644 --- a/docs/core_components/snippets.rst +++ b/docs/core_components/snippets.rst @@ -151,7 +151,7 @@ To attach multiple adverts to a page, the ``SnippetChooserPanel`` can be placed ... BookPage.content_panels = [ - InlinePanel(BookPage, 'advert_placements', label="Adverts"), + InlinePanel('advert_placements', label="Adverts"), # ... ] diff --git a/runtests.py b/runtests.py index 7961d2e19..a1925f907 100755 --- a/runtests.py +++ b/runtests.py @@ -15,6 +15,7 @@ os.environ['DJANGO_SETTINGS_MODULE'] = 'wagtail.tests.settings' def runtests(): # Don't ignore DeprecationWarnings warnings.simplefilter('default', DeprecationWarning) + warnings.simplefilter('default', PendingDeprecationWarning) argv = sys.argv[:1] + ['test'] + sys.argv[1:] try: diff --git a/wagtail/tests/models.py b/wagtail/tests/models.py index 2b20d7a7c..c419de7c7 100644 --- a/wagtail/tests/models.py +++ b/wagtail/tests/models.py @@ -247,10 +247,10 @@ EventPage.content_panels = [ FieldPanel('audience'), FieldPanel('cost'), FieldPanel('signup_link'), - InlinePanel(EventPage, 'carousel_items', label="Carousel items"), + InlinePanel('carousel_items', label="Carousel items"), FieldPanel('body', classname="full"), - InlinePanel(EventPage, 'speakers', label="Speakers"), - InlinePanel(EventPage, 'related_links', label="Related links"), + InlinePanel('speakers', label="Speakers"), + InlinePanel('related_links', label="Related links"), ] EventPage.promote_panels = [ @@ -329,7 +329,7 @@ class FormPage(AbstractEmailForm): FormPage.content_panels = [ FieldPanel('title', classname="full title"), - InlinePanel(FormPage, 'form_fields', label="Form fields"), + InlinePanel('form_fields', label="Form fields"), MultiFieldPanel([ FieldPanel('to_address', classname="full"), FieldPanel('from_address', classname="full"), @@ -392,7 +392,7 @@ class StandardIndex(Page): StandardIndex.content_panels = [ FieldPanel('title', classname="full title"), - InlinePanel(StandardIndex, 'advert_placements', label="Adverts"), + InlinePanel('advert_placements', label="Adverts"), ] diff --git a/wagtail/tests/utils.py b/wagtail/tests/utils.py index fd155e6b4..f2993df6f 100644 --- a/wagtail/tests/utils.py +++ b/wagtail/tests/utils.py @@ -1,5 +1,6 @@ from contextlib import contextmanager import warnings +import sys from django.contrib.auth import get_user_model from django.utils import six @@ -28,3 +29,18 @@ class WagtailTestUtils(object): for w in warning_list: if not issubclass(w.category, DeprecationWarning): warnings.showwarning(message=w.message, category=w.category, filename=w.filename, lineno=w.lineno, file=w.file, line=w.line) + + # borrowed from https://github.com/django/django/commit/9f427617e4559012e1c2fd8fce46cbe225d8515d + @staticmethod + def reset_warning_registry(): + """ + Clear warning registry for all modules. This is required in some tests + because of a bug in Python that prevents warnings.simplefilter("always") + from always making warnings appear: http://bugs.python.org/issue4180 + + The bug was fixed in Python 3.4.2. + """ + key = "__warningregistry__" + for mod in sys.modules.values(): + if hasattr(mod, key): + getattr(mod, key).clear() diff --git a/wagtail/wagtailadmin/edit_handlers.py b/wagtail/wagtailadmin/edit_handlers.py index 93c1e09f9..47a6b666d 100644 --- a/wagtail/wagtailadmin/edit_handlers.py +++ b/wagtail/wagtailadmin/edit_handlers.py @@ -1,6 +1,7 @@ from __future__ import unicode_literals import copy +import warnings from six import text_type @@ -21,6 +22,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.deprecation import RemovedInWagtail11Warning FORM_FIELD_OVERRIDES = { @@ -640,13 +642,29 @@ class BaseInlinePanel(EditHandler): class InlinePanel(object): - def __init__(self, base_model, relation_name, panels=None, label='', help_text=''): - # the base_model param is now redundant; we set up relations based on the model passed to + def __init__(self, *args, **kwargs): + # prior to Wagtail 0.9, InlinePanel required two params, base_model and relation_name. + # base_model is no longer required; we set up relations based on the model passed to # bind_to_model instead - self.relation_name = relation_name - self.panels = panels - self.label = label - self.help_text = help_text + if len(args) == 1: # new-style: InlinePanel(relation_name) + self.relation_name = args[0] + elif len(args) == 2: # old-style: InlinePanel(base_model, relation_name) + self.relation_name = args[1] + + warnings.warn( + "InlinePanel no longer needs to be passed a model parameter. " + "InlinePanel({classname}, '{relname}') should be changed to InlinePanel('{relname}')".format( + classname=args[0].__name__, relname=self.relation_name + ), RemovedInWagtail11Warning) + else: + raise TypeError("InlinePanel() takes exactly 1 argument (%d given)" % len(args)) + + self.panels = kwargs.pop('panels', None) + self.label = kwargs.pop('label', '') + self.help_text = kwargs.pop('help_text', '') + + if kwargs: + raise TypeError("InlinePanel got an unexpected keyword argument '%s'" % kwargs.keys()[0]) def bind_to_model(self, model): return type(str('_InlinePanel'), (BaseInlinePanel,), { diff --git a/wagtail/wagtailadmin/tests/test_edit_handlers.py b/wagtail/wagtailadmin/tests/test_edit_handlers.py index 6745841b5..9b76c7f2a 100644 --- a/wagtail/wagtailadmin/tests/test_edit_handlers.py +++ b/wagtail/wagtailadmin/tests/test_edit_handlers.py @@ -1,4 +1,5 @@ from datetime import date +import warnings from django.core.exceptions import ImproperlyConfigured from django.test import TestCase @@ -19,6 +20,8 @@ from wagtail.wagtailadmin.widgets import AdminPageChooser, AdminDateInput from wagtail.wagtailimages.edit_handlers import ImageChooserPanel from wagtail.wagtailcore.models import Page, Site from wagtail.tests.models import PageChooserModel, EventPage, EventPageSpeaker +from wagtail.tests.utils import WagtailTestUtils +from wagtail.utils.deprecation import RemovedInWagtail11Warning class TestGetFormForModel(TestCase): @@ -129,7 +132,7 @@ class TestTabbedInterface(TestCase): FieldPanel('date_to'), ], heading='Event details', classname="shiny"), ObjectList([ - InlinePanel(EventPage, 'speakers', label="Speakers"), + InlinePanel('speakers', label="Speakers"), ], heading='Speakers'), ]).bind_to_model(EventPage) @@ -200,7 +203,7 @@ class TestObjectList(TestCase): FieldPanel('title', widget=forms.Textarea), FieldPanel('date_from'), FieldPanel('date_to'), - InlinePanel(EventPage, 'speakers', label="Speakers"), + InlinePanel('speakers', label="Speakers"), ], heading='Event details', classname="shiny").bind_to_model(EventPage) def test_get_form_class(self): @@ -391,7 +394,7 @@ class TestPageChooserPanel(TestCase): result.target_content_type) -class TestInlinePanel(TestCase): +class TestInlinePanel(TestCase, WagtailTestUtils): fixtures = ['test.json'] def test_render(self): @@ -399,7 +402,7 @@ class TestInlinePanel(TestCase): Check that the inline panel renders the panels set on the model when no 'panels' parameter is passed in the InlinePanel definition """ - SpeakerInlinePanel = InlinePanel(EventPage, 'speakers', label="Speakers").bind_to_model(EventPage) + SpeakerInlinePanel = InlinePanel('speakers', label="Speakers").bind_to_model(EventPage) EventPageForm = SpeakerInlinePanel.get_form_class(EventPage) # SpeakerInlinePanel should instruct the form class to include a 'speakers' formset @@ -434,7 +437,7 @@ class TestInlinePanel(TestCase): Check that inline panel renders the panels listed in the InlinePanel definition where one is specified """ - SpeakerInlinePanel = InlinePanel(EventPage, 'speakers', label="Speakers", panels=[ + SpeakerInlinePanel = InlinePanel('speakers', label="Speakers", panels=[ FieldPanel('first_name', widget=forms.Textarea), ImageChooserPanel('image'), ]).bind_to_model(EventPage) @@ -471,3 +474,36 @@ class TestInlinePanel(TestCase): # render_js_init must provide the JS initializer self.assertIn('var panel = InlinePanel({', panel.render_js_init()) + + def test_old_style_inlinepanel_declaration(self): + """ + Check that the deprecated form of InlinePanel declaration (where the base model is passed + as the first arg) still works + """ + self.reset_warning_registry() + with warnings.catch_warnings(record=True) as w: + SpeakerInlinePanelDef = InlinePanel(EventPage, 'speakers', label="Speakers") + + # Check that a RemovedInWagtail11Warning has been triggered + self.assertEqual(len(w), 1) + self.assertTrue(issubclass(w[-1].category, RemovedInWagtail11Warning)) + self.assertTrue("InlinePanel(EventPage, 'speakers') should be changed to InlinePanel('speakers')" in str(w[-1].message)) + + SpeakerInlinePanel = SpeakerInlinePanelDef.bind_to_model(EventPage) + EventPageForm = SpeakerInlinePanel.get_form_class(EventPage) + + # SpeakerInlinePanel should instruct the form class to include a 'speakers' formset + self.assertEqual(['speakers'], list(EventPageForm.formsets.keys())) + + event_page = EventPage.objects.get(slug='christmas') + form = EventPageForm(instance=event_page) + panel = SpeakerInlinePanel(instance=event_page, form=form) + + result = panel.render_as_field() + self.assertIn('', result) + self.assertIn('value="Father"', result) + + def test_invalid_inlinepanel_declaration(self): + self.assertRaises(TypeError, lambda: InlinePanel(label="Speakers")) + self.assertRaises(TypeError, lambda: InlinePanel(EventPage, 'speakers', 'bacon', label="Speakers")) + self.assertRaises(TypeError, lambda: InlinePanel(EventPage, 'speakers', label="Speakers", bacon="chunky")) From 6b256ed89f6b96e60a61023b707c62911c4b24d5 Mon Sep 17 00:00:00 2001 From: Matt Westcott Date: Wed, 4 Feb 2015 15:58:03 +0000 Subject: [PATCH 02/40] fix deprecation warnings to give a correct error line, and ignore warnings thrown by test_invalid_inlinepanel_declaration --- wagtail/wagtailadmin/edit_handlers.py | 2 +- wagtail/wagtailadmin/tests/test_edit_handlers.py | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/wagtail/wagtailadmin/edit_handlers.py b/wagtail/wagtailadmin/edit_handlers.py index 47a6b666d..49caf2059 100644 --- a/wagtail/wagtailadmin/edit_handlers.py +++ b/wagtail/wagtailadmin/edit_handlers.py @@ -655,7 +655,7 @@ class InlinePanel(object): "InlinePanel no longer needs to be passed a model parameter. " "InlinePanel({classname}, '{relname}') should be changed to InlinePanel('{relname}')".format( classname=args[0].__name__, relname=self.relation_name - ), RemovedInWagtail11Warning) + ), RemovedInWagtail11Warning, stacklevel=2) else: raise TypeError("InlinePanel() takes exactly 1 argument (%d given)" % len(args)) diff --git a/wagtail/wagtailadmin/tests/test_edit_handlers.py b/wagtail/wagtailadmin/tests/test_edit_handlers.py index 9b76c7f2a..57fde93a0 100644 --- a/wagtail/wagtailadmin/tests/test_edit_handlers.py +++ b/wagtail/wagtailadmin/tests/test_edit_handlers.py @@ -504,6 +504,7 @@ class TestInlinePanel(TestCase, WagtailTestUtils): self.assertIn('value="Father"', result) def test_invalid_inlinepanel_declaration(self): - self.assertRaises(TypeError, lambda: InlinePanel(label="Speakers")) - self.assertRaises(TypeError, lambda: InlinePanel(EventPage, 'speakers', 'bacon', label="Speakers")) - self.assertRaises(TypeError, lambda: InlinePanel(EventPage, 'speakers', label="Speakers", bacon="chunky")) + with self.ignore_deprecation_warnings(): + self.assertRaises(TypeError, lambda: InlinePanel(label="Speakers")) + self.assertRaises(TypeError, lambda: InlinePanel(EventPage, 'speakers', 'bacon', label="Speakers")) + self.assertRaises(TypeError, lambda: InlinePanel(EventPage, 'speakers', label="Speakers", bacon="chunky")) From 589319d4668e73b813f3e66ac08aa0564310f871 Mon Sep 17 00:00:00 2001 From: Dave Cranwell Date: Wed, 4 Feb 2015 16:37:13 +0000 Subject: [PATCH 03/40] removed pointless difference in buttons izes --- .../static/wagtailadmin/scss/components/listing.scss | 1 - 1 file changed, 1 deletion(-) diff --git a/wagtail/wagtailadmin/static/wagtailadmin/scss/components/listing.scss b/wagtail/wagtailadmin/static/wagtailadmin/scss/components/listing.scss index 10b4bf7eb..e7645b5bb 100644 --- a/wagtail/wagtailadmin/static/wagtailadmin/scss/components/listing.scss +++ b/wagtail/wagtailadmin/static/wagtailadmin/scss/components/listing.scss @@ -199,7 +199,6 @@ ul.listing{ color:$color-teal; border-color:$color-grey-3; background:white; - font-size:0.84em; /* 0.01em difference to regular small buttons */ &:hover{ border-color:$color-teal; From e5e79d2e2b2f64e88660d485fb40a3e0eb200895 Mon Sep 17 00:00:00 2001 From: Dave Cranwell Date: Wed, 4 Feb 2015 16:42:03 +0000 Subject: [PATCH 04/40] fixing ugly text flush against menu edge --- .../static/wagtailadmin/scss/components/main-nav.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wagtail/wagtailadmin/static/wagtailadmin/scss/components/main-nav.scss b/wagtail/wagtailadmin/static/wagtailadmin/scss/components/main-nav.scss index a1e3265d2..40e227914 100644 --- a/wagtail/wagtailadmin/static/wagtailadmin/scss/components/main-nav.scss +++ b/wagtail/wagtailadmin/static/wagtailadmin/scss/components/main-nav.scss @@ -126,7 +126,7 @@ $submenu-color:darken($color-grey-1, 5%); .menu-item a{ white-space:normal; - padding: 0.9em 0 0.9em 4.5em; + padding: 0.9em 1.7em 0.9em 4.5em; &:before{ margin-left:-1.5em; From e7a19de2351fcb1a5fcb17cd1e581b14a2ba192f Mon Sep 17 00:00:00 2001 From: Dave Cranwell Date: Wed, 4 Feb 2015 17:09:19 +0000 Subject: [PATCH 05/40] updated styleguide to demonstrate generic image/doc/page picker ui --- .../templates/wagtailstyleguide/base.html | 79 +++++++++---------- wagtail/contrib/wagtailstyleguide/views.py | 19 ++++- 2 files changed, 57 insertions(+), 41 deletions(-) diff --git a/wagtail/contrib/wagtailstyleguide/templates/wagtailstyleguide/base.html b/wagtail/contrib/wagtailstyleguide/templates/wagtailstyleguide/base.html index 53697e82d..89f6704c4 100644 --- a/wagtail/contrib/wagtailstyleguide/templates/wagtailstyleguide/base.html +++ b/wagtail/contrib/wagtailstyleguide/templates/wagtailstyleguide/base.html @@ -347,8 +347,12 @@ {% for field in example_form %} {% if field.name == 'file' %} {% include "wagtailimages/images/_file_field.html" %} - {% elif field.name == 'date' %} - {% include "wagtailadmin/shared/field_as_li.html" with input_classes="iconfield icon-date" %} + {% elif field.name == 'page_chooser' %} +
  • {% include "wagtailadmin/edit_handlers/page_chooser_panel.html" with field=field choose_one_text_str="Choose a page" choose_another_text_str="Choose another page" only %}
  • + {% elif field.name == 'image_chooser' %} +
  • {% include "wagtailimages/edit_handlers/image_chooser_panel.html" with field=field choose_one_text_str="Choose an image" choose_another_text_str="Choose another image" only %}
  • + {% elif field.name == 'document_chooser' %} +
  • {% include "wagtaildocs/edit_handlers/document_chooser_panel.html" with field=field choose_one_text_str="Choose a document" choose_another_text_str="Choose another document" only %}
  • {% else %} {% include "wagtailadmin/shared/field_as_li.html" %} {% endif %} @@ -357,13 +361,7 @@ -

    TODO: Date picker

    -

    TODO: Time picker

    -

    TODO: Datetime picker

    TODO: Rich text input

    -

    TODO: Page chooser

    -

    TODO: Image chooser

    -

    TODO: Document chooser

    TODO: Snippet chooser

    @@ -532,42 +530,43 @@ {% endblock %} {% block extra_js %} - + (function runprogress(){ + var to = setTimeout(function(){ + runprogress(); + clearTimeout(to); + var to2 = setTimeout(function(){ + $('#progress-example .bar').css('width', '20%'); + }, 2000); + }, 3000); + $('#progress-example .bar').css('width', '80%'); + })(); + }) + {% endblock %} \ No newline at end of file diff --git a/wagtail/contrib/wagtailstyleguide/views.py b/wagtail/contrib/wagtailstyleguide/views.py index 98112adcb..4b8139e6f 100644 --- a/wagtail/contrib/wagtailstyleguide/views.py +++ b/wagtail/contrib/wagtailstyleguide/views.py @@ -5,9 +5,21 @@ from wagtail.wagtailadmin import messages from django.contrib.auth.decorators import permission_required from wagtail.wagtailadmin.forms import SearchForm - +from wagtail.wagtailadmin.widgets import AdminPageChooser, AdminDateInput, AdminTimeInput, AdminDateTimeInput +from wagtail.wagtailimages.widgets import AdminImageChooser +from wagtail.wagtaildocs.widgets import AdminDocumentChooser class ExampleForm(forms.Form): + + def __init__(self, *args, **kwargs): + super(ExampleForm, self).__init__(*args, **kwargs) + self.fields['page_chooser'].widget = AdminPageChooser() + self.fields['image_chooser'].widget = AdminImageChooser() + self.fields['document_chooser'].widget = AdminDocumentChooser() + self.fields['date'].widget = AdminDateInput() + self.fields['time'].widget = AdminTimeInput() + self.fields['datetime'].widget = AdminDateTimeInput() + CHOICES = ( ('choice1', 'choice 1'), ('choice2', 'choice 2'), @@ -18,8 +30,13 @@ class ExampleForm(forms.Form): email = forms.EmailField(max_length=254) date = forms.DateField() time = forms.TimeField() + datetime = forms.DateTimeField() select = forms.ChoiceField(choices=CHOICES) boolean = forms.BooleanField(required=False) + page_chooser = forms.BooleanField(required=True) + image_chooser = forms.BooleanField(required=True) + document_chooser = forms.BooleanField(required=True) + @permission_required('wagtailadmin.access_admin') From 577183ba898723a828a2fdb7f34b93d65e49090f Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Wed, 4 Feb 2015 20:19:17 +0000 Subject: [PATCH 06/40] Added some tests for vary key generation --- .../tests/test_image_operations.py | 32 ++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/wagtail/wagtailimages/tests/test_image_operations.py b/wagtail/wagtailimages/tests/test_image_operations.py index f4dce9642..36d77c2e8 100644 --- a/wagtail/wagtailimages/tests/test_image_operations.py +++ b/wagtail/wagtailimages/tests/test_image_operations.py @@ -2,7 +2,7 @@ import unittest from wagtail.wagtailimages import image_operations from wagtail.wagtailimages.exceptions import InvalidFilterSpecError -from wagtail.wagtailimages.models import Image +from wagtail.wagtailimages.models import Image, Filter class WillowOperationRecorder(object): @@ -318,3 +318,33 @@ class TestWidthHeightOperation(ImageOperationTestCase): ] TestWidthHeightOperation.setup_test_methods() + + +class TestVaryKey(unittest.TestCase): + def test_vary_key(self): + image = Image(width=1000, height=1000) + fil = Filter(spec='max-100x100') + vary_key = fil.get_vary_key(image) + + self.assertEqual(vary_key, 'da39a3ee') + + def test_vary_key_fill_filter(self): + image = Image(width=1000, height=1000) + fil = Filter(spec='fill-100x100') + vary_key = fil.get_vary_key(image) + + self.assertEqual(vary_key, 'da39a3ee') + + def test_vary_key_fill_filter_with_focal_point(self): + image = Image( + width=1000, + height=1000, + focal_point_width=100, + focal_point_height=100, + focal_point_x=500, + focal_point_y=500, + ) + fil = Filter(spec='fill-100x100') + vary_key = fil.get_vary_key(image) + + self.assertEqual(vary_key, 'fa9841ef') From 3b37a52a255e023286d1094902b86c920d65eca8 Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Wed, 4 Feb 2015 20:44:41 +0000 Subject: [PATCH 07/40] Replaced get_vary with vary_fields --- wagtail/wagtailimages/image_operations.py | 17 ++--------------- wagtail/wagtailimages/models.py | 6 ++++-- .../tests/test_image_operations.py | 2 +- 3 files changed, 7 insertions(+), 18 deletions(-) diff --git a/wagtail/wagtailimages/image_operations.py b/wagtail/wagtailimages/image_operations.py index 3a7884a08..9eb86a067 100644 --- a/wagtail/wagtailimages/image_operations.py +++ b/wagtail/wagtailimages/image_operations.py @@ -38,6 +38,8 @@ class DoNothingOperation(Operation): class FillOperation(Operation): + vary_fields = ('focal_point_width', 'focal_point_height', 'focal_point_x', 'focal_point_y') + def construct(self, size, *extra): # Get width and height width_str, height_str = size.split('x') @@ -175,21 +177,6 @@ class FillOperation(Operation): willow.resize(width, height) - def get_vary(self, image): - focal_point = image.get_focal_point() - - if focal_point is not None: - focal_point_key = "%(x)d-%(y)d-%(width)dx%(height)d" % { - 'x': int(focal_point.centroid_x), - 'y': int(focal_point.centroid_y), - 'width': int(focal_point.width), - 'height': int(focal_point.height), - } - else: - focal_point_key = '' - - return [focal_point_key] - class MinMaxOperation(Operation): def construct(self, size): diff --git a/wagtail/wagtailimages/models.py b/wagtail/wagtailimages/models.py index abda78a18..1fcb2ed80 100644 --- a/wagtail/wagtailimages/models.py +++ b/wagtail/wagtailimages/models.py @@ -302,8 +302,10 @@ class Filter(models.Model): vary = [] for operation in self.operations: - if hasattr(operation, 'get_vary'): - vary.extend(operation.get_vary(image)) + for field in getattr(operation, 'vary_fields', []): + value = getattr(image, field) + if value is not None: + vary.append(str(value)) return vary diff --git a/wagtail/wagtailimages/tests/test_image_operations.py b/wagtail/wagtailimages/tests/test_image_operations.py index 36d77c2e8..fc8028cc2 100644 --- a/wagtail/wagtailimages/tests/test_image_operations.py +++ b/wagtail/wagtailimages/tests/test_image_operations.py @@ -347,4 +347,4 @@ class TestVaryKey(unittest.TestCase): fil = Filter(spec='fill-100x100') vary_key = fil.get_vary_key(image) - self.assertEqual(vary_key, 'fa9841ef') + self.assertEqual(vary_key, '0bbe3b2f') From 09f053ce1e11a0092ada5d190a95942833f4da09 Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Wed, 4 Feb 2015 20:49:45 +0000 Subject: [PATCH 08/40] Make vary_key a blank string if there are no vary fields This addresses an issue which causes all renditions in a project to be regenerated after an upgrade to Wagtail 0.9. --- wagtail/wagtailimages/models.py | 6 ++++-- wagtail/wagtailimages/tests/test_image_operations.py | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/wagtail/wagtailimages/models.py b/wagtail/wagtailimages/models.py index 1fcb2ed80..4fa0f6d79 100644 --- a/wagtail/wagtailimages/models.py +++ b/wagtail/wagtailimages/models.py @@ -311,10 +311,12 @@ class Filter(models.Model): def get_vary_key(self, image): vary_string = '-'.join(self.get_vary(image)) - vary_key = hashlib.sha1(vary_string.encode('utf-8')).hexdigest() - return vary_key[:8] + # Return blank string if there are no vary fields + if not vary_string: + return '' + return hashlib.sha1(vary_string.encode('utf-8')).hexdigest()[:8] _registered_operations = None diff --git a/wagtail/wagtailimages/tests/test_image_operations.py b/wagtail/wagtailimages/tests/test_image_operations.py index fc8028cc2..0218bce7d 100644 --- a/wagtail/wagtailimages/tests/test_image_operations.py +++ b/wagtail/wagtailimages/tests/test_image_operations.py @@ -326,14 +326,14 @@ class TestVaryKey(unittest.TestCase): fil = Filter(spec='max-100x100') vary_key = fil.get_vary_key(image) - self.assertEqual(vary_key, 'da39a3ee') + self.assertEqual(vary_key, '') def test_vary_key_fill_filter(self): image = Image(width=1000, height=1000) fil = Filter(spec='fill-100x100') vary_key = fil.get_vary_key(image) - self.assertEqual(vary_key, 'da39a3ee') + self.assertEqual(vary_key, '') def test_vary_key_fill_filter_with_focal_point(self): image = Image( From 0564bd6880f857e71c4b535b860908d2c7f46ece Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Wed, 4 Feb 2015 20:58:10 +0000 Subject: [PATCH 09/40] Add fields into vary even if they dont have a value --- wagtail/wagtailimages/models.py | 5 ++--- wagtail/wagtailimages/tests/test_image_operations.py | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/wagtail/wagtailimages/models.py b/wagtail/wagtailimages/models.py index 4fa0f6d79..ad5fb63e6 100644 --- a/wagtail/wagtailimages/models.py +++ b/wagtail/wagtailimages/models.py @@ -303,9 +303,8 @@ class Filter(models.Model): for operation in self.operations: for field in getattr(operation, 'vary_fields', []): - value = getattr(image, field) - if value is not None: - vary.append(str(value)) + value = getattr(image, field, '') + vary.append(str(value)) return vary diff --git a/wagtail/wagtailimages/tests/test_image_operations.py b/wagtail/wagtailimages/tests/test_image_operations.py index 0218bce7d..ba7634e34 100644 --- a/wagtail/wagtailimages/tests/test_image_operations.py +++ b/wagtail/wagtailimages/tests/test_image_operations.py @@ -333,7 +333,7 @@ class TestVaryKey(unittest.TestCase): fil = Filter(spec='fill-100x100') vary_key = fil.get_vary_key(image) - self.assertEqual(vary_key, '') + self.assertEqual(vary_key, '2e16d0ba') def test_vary_key_fill_filter_with_focal_point(self): image = Image( From 54210e9fe431d7eb25b276da5cbe513f0defb948 Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Wed, 4 Feb 2015 21:07:11 +0000 Subject: [PATCH 10/40] Fixed test Dictionary was being mutated while iterating over its values. --- wagtail/tests/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wagtail/tests/utils.py b/wagtail/tests/utils.py index f2993df6f..f4cd561ab 100644 --- a/wagtail/tests/utils.py +++ b/wagtail/tests/utils.py @@ -41,6 +41,6 @@ class WagtailTestUtils(object): The bug was fixed in Python 3.4.2. """ key = "__warningregistry__" - for mod in sys.modules.values(): + for mod in list(sys.modules.values()): if hasattr(mod, key): getattr(mod, key).clear() From 182aa6922adc3e4a291473ba020e00af11d54ceb Mon Sep 17 00:00:00 2001 From: Dave Cranwell Date: Thu, 5 Feb 2015 09:34:07 +0000 Subject: [PATCH 11/40] added suitable message when no snippets of a particular type exist --- .../templates/wagtailsnippets/chooser/choose.html | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/wagtail/wagtailsnippets/templates/wagtailsnippets/chooser/choose.html b/wagtail/wagtailsnippets/templates/wagtailsnippets/chooser/choose.html index 8346e9b9d..969f4cd4d 100644 --- a/wagtail/wagtailsnippets/templates/wagtailsnippets/chooser/choose.html +++ b/wagtail/wagtailsnippets/templates/wagtailsnippets/chooser/choose.html @@ -3,5 +3,10 @@ {% include "wagtailadmin/shared/header.html" with title=choose_str subtitle=snippet_type_name icon="snippet" %}
    - {% include "wagtailsnippets/snippets/list.html" with choosing=1 %} + {% if items %} + {% include "wagtailsnippets/snippets/list.html" with choosing=1 %} + {% else %} + {% url 'wagtailsnippets_create' content_type.app_label content_type.model as wagtailsnippets_create_snippet_url %} +

    {% blocktrans %}You haven't created any {{ snippet_type_name }} snippets. Why not create one now{% endblocktrans %}

    + {% endif %}
    From 43641192c20d4de19f662dd7828919b24386ae16 Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Fri, 6 Feb 2015 09:57:42 +0000 Subject: [PATCH 12/40] Fixed a couple of references to django.forms.util --- wagtail/wagtailadmin/menu.py | 7 +------ wagtail/wagtailembeds/views/chooser.py | 2 +- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/wagtail/wagtailadmin/menu.py b/wagtail/wagtailadmin/menu.py index df8bf7637..5fa4ff7cf 100644 --- a/wagtail/wagtailadmin/menu.py +++ b/wagtail/wagtailadmin/menu.py @@ -2,13 +2,8 @@ from __future__ import unicode_literals from six import text_type, with_metaclass -try: - # renamed util -> utils in Django 1.7; try the new name first - from django.forms.utils import flatatt -except ImportError: - from django.forms.util import flatatt - from django.forms import MediaDefiningClass, Media +from django.forms.utils import flatatt from django.utils.text import slugify from django.utils.html import format_html from django.utils.safestring import mark_safe diff --git a/wagtail/wagtailembeds/views/chooser.py b/wagtail/wagtailembeds/views/chooser.py index 5892ed91b..da10e802e 100644 --- a/wagtail/wagtailembeds/views/chooser.py +++ b/wagtail/wagtailembeds/views/chooser.py @@ -1,4 +1,4 @@ -from django.forms.util import ErrorList +from django.forms.utils import ErrorList from django.utils.translation import ugettext as _ from wagtail.wagtailadmin.modal_workflow import render_modal_workflow From a5edb0ce0f6452b7c49404918f70d5cba670bc6e Mon Sep 17 00:00:00 2001 From: Dave Cranwell Date: Fri, 6 Feb 2015 10:03:49 +0000 Subject: [PATCH 13/40] tweak to zindex of autocomplete widget --- .../static/wagtailadmin/scss/components/forms.scss | 3 +++ 1 file changed, 3 insertions(+) diff --git a/wagtail/wagtailadmin/static/wagtailadmin/scss/components/forms.scss b/wagtail/wagtailadmin/static/wagtailadmin/scss/components/forms.scss index 65abb480b..2639eb244 100644 --- a/wagtail/wagtailadmin/static/wagtailadmin/scss/components/forms.scss +++ b/wagtail/wagtailadmin/static/wagtailadmin/scss/components/forms.scss @@ -736,6 +736,9 @@ ul.tagit input[type="text"]{ ul.tagit li.tagit-choice-editable{ padding:0 23px 0 0 !important; /* having to use important, FML*/ } +.ui-front{ /* provided by jqueryui but not high enough an index */ + z-index:1000; +} .tagit-close{ .ui-icon-close{ From cf0e17d94c834c17ac30f3e21a1258688bdd7d53 Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Fri, 6 Feb 2015 10:22:38 +0000 Subject: [PATCH 14/40] Added tests for resolve_model_string To make sure I don't change its behaviour in the next commit --- wagtail/wagtailcore/tests/tests.py | 42 ++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/wagtail/wagtailcore/tests/tests.py b/wagtail/wagtailcore/tests/tests.py index 7cc1509cd..c53494648 100644 --- a/wagtail/wagtailcore/tests/tests.py +++ b/wagtail/wagtailcore/tests/tests.py @@ -1,7 +1,10 @@ +import unittest + from django.test import TestCase from django.core.cache import cache from wagtail.wagtailcore.models import Page, Site +from wagtail.wagtailcore.utils import resolve_model_string from wagtail.tests.models import SimplePage @@ -142,3 +145,42 @@ class TestSiteRootPathsCache(TestCase): # Check url self.assertEqual(homepage.url, '/') + + +class TestResolveModelString(TestCase): + def test_resolve_from_string(self): + model = resolve_model_string('wagtailcore.Page') + + self.assertEqual(model, Page) + + def test_resolve_from_string_with_default_app(self): + model = resolve_model_string('Page', default_app='wagtailcore') + + self.assertEqual(model, Page) + + def test_resolve_from_string_with_different_default_app(self): + model = resolve_model_string('wagtailcore.Page', default_app='wagtailadmin') + + self.assertEqual(model, Page) + + def test_resolve_from_class(self): + model = resolve_model_string(Page) + + self.assertEqual(model, Page) + + def test_resolve_from_string_invalid(self): + self.assertRaises(ValueError, resolve_model_string, 'wagtail.wagtailcore.Page') + + def test_resolve_from_string_with_incorrect_default_app(self): + self.assertRaises(LookupError, resolve_model_string, 'Page', default_app='wagtailadmin') + + def test_resolve_from_string_with_no_default_app(self): + self.assertRaises(ValueError, resolve_model_string, 'Page') + + @unittest.expectedFailure # Raising LookupError instead + def test_resolve_from_class_that_isnt_a_model(self): + self.assertRaises(ValueError, resolve_model_string, object) + + @unittest.expectedFailure # Raising LookupError instead + def test_resolve_from_bad_type(self): + self.assertRaises(ValueError, resolve_model_string, resolve_model_string) From 354a5aaa8025f5f5e9f3ae628a4e5bff8aadc2f1 Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Fri, 6 Feb 2015 10:25:42 +0000 Subject: [PATCH 15/40] Removed reference to django.db.get_models in resolve_model_string --- wagtail/wagtailcore/utils.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/wagtail/wagtailcore/utils.py b/wagtail/wagtailcore/utils.py index 1880684bc..fbff60abb 100644 --- a/wagtail/wagtailcore/utils.py +++ b/wagtail/wagtailcore/utils.py @@ -1,7 +1,9 @@ import re -from django.db.models import Model, get_model from six import string_types +from django.db.models import Model +from django.apps import apps + def camelcase_to_underscore(str): # http://djangosnippets.org/snippets/585/ @@ -26,10 +28,7 @@ def resolve_model_string(model_string, default_app=None): "should be in the form app_label.model_name".format( model_string), model_string) - model = get_model(app_label, model_name) - if not model: - raise LookupError("Can not resolve {0!r} into a model".format(model_string), model_string) - return model + return apps.get_model(app_label, model_name) elif isinstance(model_string, type) and issubclass(model_string, Model): return model_string From 9cf1a81034eb372d391dcf68e8c6c1896d5365b5 Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Fri, 6 Feb 2015 10:28:07 +0000 Subject: [PATCH 16/40] Fixed another reference to django.db.get_models --- wagtail/wagtailcore/query.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/wagtail/wagtailcore/query.py b/wagtail/wagtailcore/query.py index cc86d52b7..8911fe8be 100644 --- a/wagtail/wagtailcore/query.py +++ b/wagtail/wagtailcore/query.py @@ -1,5 +1,7 @@ -from django.db.models import Q, get_models +from django.db.models import Q from django.contrib.contenttypes.models import ContentType +from django.apps import apps + from treebeard.mp_tree import MP_NodeQuerySet from wagtail.wagtailsearch.backends import get_search_backend @@ -154,7 +156,7 @@ class PageQuerySet(MP_NodeQuerySet): def type_q(self, klass): content_types = ContentType.objects.get_for_models(*[ - model for model in get_models() + model for model in apps.get_models() if issubclass(model, klass) ]).values() From d0b0d57ca5e5ff2940fe2364e3453b26550549ba Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Fri, 6 Feb 2015 10:34:39 +0000 Subject: [PATCH 17/40] Ignore PendingDeprecationWarnings --- wagtail/tests/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wagtail/tests/utils.py b/wagtail/tests/utils.py index f4cd561ab..1abfb0116 100644 --- a/wagtail/tests/utils.py +++ b/wagtail/tests/utils.py @@ -25,9 +25,9 @@ class WagtailTestUtils(object): with warnings.catch_warnings(record=True) as warning_list: # catch all warnings yield - # rethrow all warnings that were not DeprecationWarnings + # rethrow all warnings that were not DeprecationWarnings or PendingDeprecationWarnings for w in warning_list: - if not issubclass(w.category, DeprecationWarning): + if not issubclass(w.category, (DeprecationWarning, PendingDeprecationWarning)): warnings.showwarning(message=w.message, category=w.category, filename=w.filename, lineno=w.lineno, file=w.file, line=w.line) # borrowed from https://github.com/django/django/commit/9f427617e4559012e1c2fd8fce46cbe225d8515d From 50e4cdf8b8306c64f46d5629ea7bf50b0a51145b Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Fri, 6 Feb 2015 10:39:04 +0000 Subject: [PATCH 18/40] Replaced SortedDict with OrderedDict --- wagtail/wagtailforms/forms.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/wagtail/wagtailforms/forms.py b/wagtail/wagtailforms/forms.py index b91a378f6..2c1ba5fea 100644 --- a/wagtail/wagtailforms/forms.py +++ b/wagtail/wagtailforms/forms.py @@ -1,5 +1,6 @@ +from collections import OrderedDict + import django.forms -from django.utils.datastructures import SortedDict class BaseForm(django.forms.Form): @@ -75,7 +76,7 @@ class FormBuilder(object): @property def formfields(self): - formfields = SortedDict() + formfields = OrderedDict() for field in self.fields: options = self.get_field_options(field) From 61bd2511a821900fd2b707b14e72bc41834264a7 Mon Sep 17 00:00:00 2001 From: Matt Westcott Date: Fri, 6 Feb 2015 12:15:34 +0000 Subject: [PATCH 19/40] Don't bother to pass show_help_text to templates, because no templates ever use it. This means that the show_help_text parameter to render_as_field now has no effect, so we can safely remove it from the one call that uses it --- wagtail/wagtailadmin/edit_handlers.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/wagtail/wagtailadmin/edit_handlers.py b/wagtail/wagtailadmin/edit_handlers.py index 49caf2059..a67dcd468 100644 --- a/wagtail/wagtailadmin/edit_handlers.py +++ b/wagtail/wagtailadmin/edit_handlers.py @@ -422,7 +422,7 @@ class BaseFieldPanel(EditHandler): def render_as_object(self): return mark_safe(render_to_string(self.object_template, { 'self': self, - 'field_content': self.render_as_field(show_help_text=False), + 'field_content': self.render_as_field(), })) field_template = "wagtailadmin/edit_handlers/field_panel_field.html" @@ -431,7 +431,6 @@ class BaseFieldPanel(EditHandler): context = { 'field': self.bound_field, 'field_type': self.field_type(), - 'show_help_text': show_help_text, } context.update(extra_context) return mark_safe(render_to_string(self.field_template, context)) @@ -502,7 +501,6 @@ class BaseChooserPanel(BaseFieldPanel): 'field': self.bound_field, self.object_type_name: instance_obj, 'is_chosen': bool(instance_obj), - 'show_help_text': show_help_text, } context.update(extra_context) return mark_safe(render_to_string(self.field_template, context)) From e3216fad45f8a57a197afeb69af695482ed82946 Mon Sep 17 00:00:00 2001 From: Matt Westcott Date: Fri, 6 Feb 2015 12:21:41 +0000 Subject: [PATCH 20/40] now the only call to render_as_field with any parameters whatsoever is where BasePageChooserPanel.render_as_field calls super - so only BaseChooserPanel.render_as_field needs to retain those parameters, and only extra_context --- wagtail/wagtailadmin/edit_handlers.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/wagtail/wagtailadmin/edit_handlers.py b/wagtail/wagtailadmin/edit_handlers.py index a67dcd468..5e490dd9a 100644 --- a/wagtail/wagtailadmin/edit_handlers.py +++ b/wagtail/wagtailadmin/edit_handlers.py @@ -427,12 +427,11 @@ class BaseFieldPanel(EditHandler): field_template = "wagtailadmin/edit_handlers/field_panel_field.html" - def render_as_field(self, show_help_text=True, extra_context={}): + def render_as_field(self): context = { 'field': self.bound_field, 'field_type': self.field_type(), } - context.update(extra_context) return mark_safe(render_to_string(self.field_template, context)) @classmethod @@ -495,7 +494,7 @@ class BaseChooserPanel(BaseFieldPanel): # like every other unpopulated field type. Yay consistency! return None - def render_as_field(self, show_help_text=True, extra_context={}): + def render_as_field(self, extra_context={}): instance_obj = self.get_chosen_item() context = { 'field': self.bound_field, @@ -537,13 +536,12 @@ class BasePageChooserPanel(BaseChooserPanel): return cls._target_content_type - def render_as_field(self, show_help_text=True, extra_context={}): + def render_as_field(self): context = { 'choose_another_text_str': ugettext_lazy("Choose another page"), 'choose_one_text_str': ugettext_lazy("Choose a page"), } - context.update(extra_context) - return super(BasePageChooserPanel, self).render_as_field(show_help_text, context) + return super(BasePageChooserPanel, self).render_as_field(extra_context=context) class PageChooserPanel(object): From e8246f6c4bdeb63aee809048c8d69a4119002e1c Mon Sep 17 00:00:00 2001 From: Matt Westcott Date: Fri, 6 Feb 2015 12:54:09 +0000 Subject: [PATCH 21/40] introduce a common AdminChooser superclass for all our Admin*Choosers --- wagtail/wagtailadmin/widgets.py | 5 ++++- wagtail/wagtaildocs/widgets.py | 8 ++------ wagtail/wagtailimages/widgets.py | 8 ++------ wagtail/wagtailsnippets/widgets.py | 7 ++----- 4 files changed, 10 insertions(+), 18 deletions(-) diff --git a/wagtail/wagtailadmin/widgets.py b/wagtail/wagtailadmin/widgets.py index f8282082c..3b12b95d2 100644 --- a/wagtail/wagtailadmin/widgets.py +++ b/wagtail/wagtailadmin/widgets.py @@ -34,8 +34,11 @@ class AdminTagWidget(WidgetWithScript, TagWidget): json.dumps(reverse('wagtailadmin_tag_autocomplete'))) -class AdminPageChooser(WidgetWithScript, widgets.Input): +class AdminChooser(WidgetWithScript, widgets.Input): input_type = 'hidden' + + +class AdminPageChooser(AdminChooser): target_content_type = None def __init__(self, content_type=None, **kwargs): diff --git a/wagtail/wagtaildocs/widgets.py b/wagtail/wagtaildocs/widgets.py index fd23bec8c..643cfae66 100644 --- a/wagtail/wagtaildocs/widgets.py +++ b/wagtail/wagtaildocs/widgets.py @@ -2,13 +2,9 @@ from __future__ import absolute_import, unicode_literals import json -from django.forms import widgets - -from wagtail.utils.widgets import WidgetWithScript +from wagtail.wagtailadmin.widgets import AdminChooser -class AdminDocumentChooser(WidgetWithScript, widgets.Input): - input_type = 'hidden' - +class AdminDocumentChooser(AdminChooser): def render_js_init(self, id_, name, value): return "createDocumentChooser({0});".format(json.dumps(id_)) diff --git a/wagtail/wagtailimages/widgets.py b/wagtail/wagtailimages/widgets.py index 3580e74a1..82b278dc1 100644 --- a/wagtail/wagtailimages/widgets.py +++ b/wagtail/wagtailimages/widgets.py @@ -2,13 +2,9 @@ from __future__ import absolute_import, unicode_literals import json -from django.forms import widgets - -from wagtail.utils.widgets import WidgetWithScript +from wagtail.wagtailadmin.widgets import AdminChooser -class AdminImageChooser(WidgetWithScript, widgets.Input): - input_type = 'hidden' - +class AdminImageChooser(AdminChooser): def render_js_init(self, id_, name, value): return "createImageChooser({0});".format(json.dumps(id_)) diff --git a/wagtail/wagtailsnippets/widgets.py b/wagtail/wagtailsnippets/widgets.py index 00945e06f..7abf95a03 100644 --- a/wagtail/wagtailsnippets/widgets.py +++ b/wagtail/wagtailsnippets/widgets.py @@ -2,13 +2,10 @@ from __future__ import absolute_import, unicode_literals import json -from django.forms import widgets - -from wagtail.utils.widgets import WidgetWithScript +from wagtail.wagtailadmin.widgets import AdminChooser -class AdminSnippetChooser(WidgetWithScript, widgets.Input): - input_type = 'hidden' +class AdminSnippetChooser(AdminChooser): target_content_type = None def __init__(self, content_type=None, **kwargs): From 932f532b80cab6f125b102a72128b46706242299 Mon Sep 17 00:00:00 2001 From: Matt Westcott Date: Fri, 6 Feb 2015 14:43:54 +0000 Subject: [PATCH 22/40] Set choose_one_text, choose_another_text and clear_choice_text as overrideable properties on AdminChooser so that we don't have to do template inheritance gymnastics to pass them around --- .../templates/wagtailstyleguide/base.html | 6 +++--- wagtail/wagtailadmin/edit_handlers.py | 10 +--------- .../edit_handlers/chooser_panel.html | 6 +++--- .../edit_handlers/page_chooser_panel.html | 3 --- .../templates/wagtailadmin/pages/copy.html | 4 +--- wagtail/wagtailadmin/widgets.py | 16 ++++++++++++++++ .../edit_handlers/document_chooser_panel.html | 4 ---- wagtail/wagtaildocs/widgets.py | 5 +++++ .../edit_handlers/image_chooser_panel.html | 4 ---- wagtail/wagtailimages/widgets.py | 6 ++++++ .../editorspicks/includes/editorspicks_form.html | 6 ++---- wagtail/wagtailsites/forms.py | 5 ++++- .../templates/wagtailsites/create.html | 6 ++---- .../templates/wagtailsites/edit.html | 7 ++----- wagtail/wagtailsnippets/edit_handlers.py | 2 +- .../edit_handlers/snippet_chooser_panel.html | 3 --- wagtail/wagtailsnippets/widgets.py | 7 +++++++ .../groups/includes/page_permissions_form.html | 7 ++----- 18 files changed, 55 insertions(+), 52 deletions(-) diff --git a/wagtail/contrib/wagtailstyleguide/templates/wagtailstyleguide/base.html b/wagtail/contrib/wagtailstyleguide/templates/wagtailstyleguide/base.html index 89f6704c4..de0019f84 100644 --- a/wagtail/contrib/wagtailstyleguide/templates/wagtailstyleguide/base.html +++ b/wagtail/contrib/wagtailstyleguide/templates/wagtailstyleguide/base.html @@ -348,11 +348,11 @@ {% if field.name == 'file' %} {% include "wagtailimages/images/_file_field.html" %} {% elif field.name == 'page_chooser' %} -
  • {% include "wagtailadmin/edit_handlers/page_chooser_panel.html" with field=field choose_one_text_str="Choose a page" choose_another_text_str="Choose another page" only %}
  • +
  • {% include "wagtailadmin/edit_handlers/page_chooser_panel.html" with field=field only %}
  • {% elif field.name == 'image_chooser' %} -
  • {% include "wagtailimages/edit_handlers/image_chooser_panel.html" with field=field choose_one_text_str="Choose an image" choose_another_text_str="Choose another image" only %}
  • +
  • {% include "wagtailimages/edit_handlers/image_chooser_panel.html" with field=field only %}
  • {% elif field.name == 'document_chooser' %} -
  • {% include "wagtaildocs/edit_handlers/document_chooser_panel.html" with field=field choose_one_text_str="Choose a document" choose_another_text_str="Choose another document" only %}
  • +
  • {% include "wagtaildocs/edit_handlers/document_chooser_panel.html" with field=field only %}
  • {% else %} {% include "wagtailadmin/shared/field_as_li.html" %} {% endif %} diff --git a/wagtail/wagtailadmin/edit_handlers.py b/wagtail/wagtailadmin/edit_handlers.py index 5e490dd9a..8aa047fc5 100644 --- a/wagtail/wagtailadmin/edit_handlers.py +++ b/wagtail/wagtailadmin/edit_handlers.py @@ -494,14 +494,13 @@ class BaseChooserPanel(BaseFieldPanel): # like every other unpopulated field type. Yay consistency! return None - def render_as_field(self, extra_context={}): + def render_as_field(self): instance_obj = self.get_chosen_item() context = { 'field': self.bound_field, self.object_type_name: instance_obj, 'is_chosen': bool(instance_obj), } - context.update(extra_context) return mark_safe(render_to_string(self.field_template, context)) @@ -536,13 +535,6 @@ class BasePageChooserPanel(BaseChooserPanel): return cls._target_content_type - def render_as_field(self): - context = { - 'choose_another_text_str': ugettext_lazy("Choose another page"), - 'choose_one_text_str': ugettext_lazy("Choose a page"), - } - return super(BasePageChooserPanel, self).render_as_field(extra_context=context) - class PageChooserPanel(object): def __init__(self, field_name, page_type=None): diff --git a/wagtail/wagtailadmin/templates/wagtailadmin/edit_handlers/chooser_panel.html b/wagtail/wagtailadmin/templates/wagtailadmin/edit_handlers/chooser_panel.html index bf583c1dd..65a627479 100644 --- a/wagtail/wagtailadmin/templates/wagtailadmin/edit_handlers/chooser_panel.html +++ b/wagtail/wagtailadmin/templates/wagtailadmin/edit_handlers/chooser_panel.html @@ -17,14 +17,14 @@
    {% if not field.field.required %} - + {% endif %} - +
    - +
    diff --git a/wagtail/wagtailadmin/templates/wagtailadmin/edit_handlers/page_chooser_panel.html b/wagtail/wagtailadmin/templates/wagtailadmin/edit_handlers/page_chooser_panel.html index fbca951ca..800d40e65 100644 --- a/wagtail/wagtailadmin/templates/wagtailadmin/edit_handlers/page_chooser_panel.html +++ b/wagtail/wagtailadmin/templates/wagtailadmin/edit_handlers/page_chooser_panel.html @@ -3,6 +3,3 @@ {% block chosen_state_view %} {{ page.title }} {% endblock %} - -{% block choose_another_button_label %}{{ choose_another_text_str }}{% endblock %} -{% block choose_button_label %}{{ choose_one_text_str }}{% endblock %} diff --git a/wagtail/wagtailadmin/templates/wagtailadmin/pages/copy.html b/wagtail/wagtailadmin/templates/wagtailadmin/pages/copy.html index ef155ef9a..26f3196cb 100644 --- a/wagtail/wagtailadmin/templates/wagtailadmin/pages/copy.html +++ b/wagtail/wagtailadmin/templates/wagtailadmin/pages/copy.html @@ -15,9 +15,7 @@ {% include "wagtailadmin/shared/field_as_li.html" with field=form.new_slug %}
  • - {% trans "Change page" as choose_another_text_str %} - {% trans "Choose page" as choose_one_text_str %} - {% include "wagtailadmin/edit_handlers/page_chooser_panel.html" with field=form.new_parent_page page=parent_page is_chosen=True choose_one_text_str=choose_one_text_str choose_another_text_str=choose_another_text_str only %} + {% include "wagtailadmin/edit_handlers/page_chooser_panel.html" with field=form.new_parent_page page=parent_page is_chosen=True only %}
  • {% if form.copy_subpages %} diff --git a/wagtail/wagtailadmin/widgets.py b/wagtail/wagtailadmin/widgets.py index 3b12b95d2..7bf92a7cd 100644 --- a/wagtail/wagtailadmin/widgets.py +++ b/wagtail/wagtailadmin/widgets.py @@ -5,6 +5,7 @@ import json from django.core.urlresolvers import reverse from django.forms import widgets from django.contrib.contenttypes.models import ContentType +from django.utils.translation import ugettext_lazy as _ from wagtail.utils.widgets import WidgetWithScript from wagtail.wagtailcore.models import Page @@ -36,10 +37,25 @@ class AdminTagWidget(WidgetWithScript, TagWidget): class AdminChooser(WidgetWithScript, widgets.Input): input_type = 'hidden' + choose_one_text = _("Choose an item") + choose_another_text = _("Choose another item") + clear_choice_text = _("Clear choice") + + def __init__(self, **kwargs): + # allow choose_one_text / choose_another_text to be overridden per-instance + if 'choose_one_text' in kwargs: + self.choose_one_text = kwargs.pop('choose_one_text') + if 'choose_another_text' in kwargs: + self.choose_another_text = kwargs.pop('choose_another_text') + if 'clear_choice_text' in kwargs: + self.clear_choice_text = kwargs.pop('clear_choice_text') + super(AdminChooser, self).__init__(**kwargs) class AdminPageChooser(AdminChooser): target_content_type = None + choose_one_text = _('Choose a page') + choose_another_text = _('Choose another page') def __init__(self, content_type=None, **kwargs): super(AdminPageChooser, self).__init__(**kwargs) diff --git a/wagtail/wagtaildocs/templates/wagtaildocs/edit_handlers/document_chooser_panel.html b/wagtail/wagtaildocs/templates/wagtaildocs/edit_handlers/document_chooser_panel.html index cc3f679cc..59dc2ed2a 100644 --- a/wagtail/wagtaildocs/templates/wagtaildocs/edit_handlers/document_chooser_panel.html +++ b/wagtail/wagtaildocs/templates/wagtaildocs/edit_handlers/document_chooser_panel.html @@ -5,7 +5,3 @@ {% block chosen_state_view %} {{ document.title }} {% endblock %} - -{% block clear_button_label %}{% trans "Clear choice" %}{% endblock %} -{% block choose_another_button_label %}{% trans "Choose another document" %}{% endblock %} -{% block choose_button_label %}{% trans "Choose a document" %}{% endblock %} diff --git a/wagtail/wagtaildocs/widgets.py b/wagtail/wagtaildocs/widgets.py index 643cfae66..e5d490f51 100644 --- a/wagtail/wagtaildocs/widgets.py +++ b/wagtail/wagtaildocs/widgets.py @@ -2,9 +2,14 @@ from __future__ import absolute_import, unicode_literals import json +from django.utils.translation import ugettext_lazy as _ + from wagtail.wagtailadmin.widgets import AdminChooser class AdminDocumentChooser(AdminChooser): + choose_one_text = _('Choose a document') + choose_another_text = _('Choose another document') + def render_js_init(self, id_, name, value): return "createDocumentChooser({0});".format(json.dumps(id_)) diff --git a/wagtail/wagtailimages/templates/wagtailimages/edit_handlers/image_chooser_panel.html b/wagtail/wagtailimages/templates/wagtailimages/edit_handlers/image_chooser_panel.html index abae4c905..38df1be80 100644 --- a/wagtail/wagtailimages/templates/wagtailimages/edit_handlers/image_chooser_panel.html +++ b/wagtail/wagtailimages/templates/wagtailimages/edit_handlers/image_chooser_panel.html @@ -13,7 +13,3 @@ {% endif %} {% endblock %} - -{% block clear_button_label %}{% trans "Clear image" %}{% endblock %} -{% block choose_another_button_label %}{% trans "Choose another image" %}{% endblock %} -{% block choose_button_label %}{% trans "Choose an image" %}{% endblock %} diff --git a/wagtail/wagtailimages/widgets.py b/wagtail/wagtailimages/widgets.py index 82b278dc1..4bce83505 100644 --- a/wagtail/wagtailimages/widgets.py +++ b/wagtail/wagtailimages/widgets.py @@ -2,9 +2,15 @@ from __future__ import absolute_import, unicode_literals import json +from django.utils.translation import ugettext_lazy as _ + from wagtail.wagtailadmin.widgets import AdminChooser class AdminImageChooser(AdminChooser): + choose_one_text = _('Choose an image') + choose_another_text = _('Choose another image') + clear_choice_text = _('Clear image') + def render_js_init(self, id_, name, value): return "createImageChooser({0});".format(json.dumps(id_)) diff --git a/wagtail/wagtailsearch/templates/wagtailsearch/editorspicks/includes/editorspicks_form.html b/wagtail/wagtailsearch/templates/wagtailsearch/editorspicks/includes/editorspicks_form.html index aae5fdabe..64fbbd724 100644 --- a/wagtail/wagtailsearch/templates/wagtailsearch/editorspicks/includes/editorspicks_form.html +++ b/wagtail/wagtailsearch/templates/wagtailsearch/editorspicks/includes/editorspicks_form.html @@ -10,12 +10,10 @@ {% trans "Promoted search result" %}
    • - {% trans "Choose another page" as choose_another_text_str %} - {% trans "Choose a page" as choose_one_text_str %} {% if form.instance.page %} - {% include "wagtailadmin/edit_handlers/page_chooser_panel.html" with field=form.page page=form.instance.page is_chosen=True choose_one_text_str=choose_one_text_str choose_another_text_str=choose_another_text_str only %} + {% include "wagtailadmin/edit_handlers/page_chooser_panel.html" with field=form.page page=form.instance.page is_chosen=True only %} {% else %} - {% include "wagtailadmin/edit_handlers/page_chooser_panel.html" with field=form.page is_chosen=False choose_one_text_str=choose_one_text_str choose_another_text_str=choose_another_text_str only %} + {% include "wagtailadmin/edit_handlers/page_chooser_panel.html" with field=form.page is_chosen=False only %} {% endif %}
    • diff --git a/wagtail/wagtailsites/forms.py b/wagtail/wagtailsites/forms.py index 7235d4313..b4f6350ba 100644 --- a/wagtail/wagtailsites/forms.py +++ b/wagtail/wagtailsites/forms.py @@ -1,4 +1,5 @@ from django import forms +from django.utils.translation import ugettext_lazy as _ from wagtail.wagtailcore.models import Site from wagtail.wagtailadmin.widgets import AdminPageChooser @@ -7,7 +8,9 @@ from wagtail.wagtailadmin.widgets import AdminPageChooser class SiteForm(forms.ModelForm): def __init__(self, *args, **kwargs): super(SiteForm, self).__init__(*args, **kwargs) - self.fields['root_page'].widget = AdminPageChooser() + self.fields['root_page'].widget = AdminPageChooser( + choose_one_text=_('Choose a root page'), choose_another_text=_('Choose a different root page') + ) required_css_class = "required" diff --git a/wagtail/wagtailsites/templates/wagtailsites/create.html b/wagtail/wagtailsites/templates/wagtailsites/create.html index 55db92061..fc8aae711 100644 --- a/wagtail/wagtailsites/templates/wagtailsites/create.html +++ b/wagtail/wagtailsites/templates/wagtailsites/create.html @@ -17,12 +17,10 @@ {% include "wagtailadmin/shared/field_as_li.html" with field=form.port %}
    • - {% trans "Choose a different root page" as choose_another_text_str %} - {% trans "Choose a root page" as choose_one_text_str %} {% if form.instance.root_page %} - {% include "wagtailadmin/edit_handlers/page_chooser_panel.html" with field=form.root_page page=form.instance.root_page is_chosen=True choose_one_text_str=choose_one_text_str choose_another_text_str=choose_another_text_str only %} + {% include "wagtailadmin/edit_handlers/page_chooser_panel.html" with field=form.root_page page=form.instance.root_page is_chosen=True only %} {% else %} - {% include "wagtailadmin/edit_handlers/page_chooser_panel.html" with field=form.root_page is_chosen=False choose_one_text_str=choose_one_text_str choose_another_text_str=choose_another_text_str only %} + {% include "wagtailadmin/edit_handlers/page_chooser_panel.html" with field=form.root_page is_chosen=False only %} {% endif %}
    • diff --git a/wagtail/wagtailsites/templates/wagtailsites/edit.html b/wagtail/wagtailsites/templates/wagtailsites/edit.html index cc04bac0e..5125e4423 100644 --- a/wagtail/wagtailsites/templates/wagtailsites/edit.html +++ b/wagtail/wagtailsites/templates/wagtailsites/edit.html @@ -18,13 +18,10 @@ {% include "wagtailadmin/shared/field_as_li.html" with field=form.port %}
    • - {% trans "Change page" as choose_another_text_str %} - {% trans "Choose page" as choose_one_text_str %} - {% if form.instance.root_page %} - {% include "wagtailadmin/edit_handlers/page_chooser_panel.html" with field=form.root_page page=form.instance.root_page is_chosen=True choose_one_text_str=choose_one_text_str choose_another_text_str=choose_another_text_str only %} + {% include "wagtailadmin/edit_handlers/page_chooser_panel.html" with field=form.root_page page=form.instance.root_page is_chosen=True only %} {% else %} - {% include "wagtailadmin/edit_handlers/page_chooser_panel.html" with field=form.root_page is_chosen=False choose_one_text_str=choose_one_text_str choose_another_text_str=choose_another_text_str only %} + {% include "wagtailadmin/edit_handlers/page_chooser_panel.html" with field=form.root_page is_chosen=False only %} {% endif %}
    • diff --git a/wagtail/wagtailsnippets/edit_handlers.py b/wagtail/wagtailsnippets/edit_handlers.py index 2e230715b..6f23d6ba3 100644 --- a/wagtail/wagtailsnippets/edit_handlers.py +++ b/wagtail/wagtailsnippets/edit_handlers.py @@ -18,7 +18,7 @@ class BaseSnippetChooserPanel(BaseChooserPanel): @classmethod def widget_overrides(cls): return {cls.field_name: AdminSnippetChooser( - content_type=cls.content_type())} + content_type=cls.content_type(), snippet_type_name=cls.snippet_type_name)} @classmethod def content_type(cls): diff --git a/wagtail/wagtailsnippets/templates/wagtailsnippets/edit_handlers/snippet_chooser_panel.html b/wagtail/wagtailsnippets/templates/wagtailsnippets/edit_handlers/snippet_chooser_panel.html index d58da6246..1dc2c40eb 100644 --- a/wagtail/wagtailsnippets/templates/wagtailsnippets/edit_handlers/snippet_chooser_panel.html +++ b/wagtail/wagtailsnippets/templates/wagtailsnippets/edit_handlers/snippet_chooser_panel.html @@ -6,6 +6,3 @@ {% block chosen_state_view %} {% if is_chosen %}{{ item }}{% endif %} {% endblock %} - -{% block choose_another_button_label %}{% blocktrans %}Choose another {{ snippet_type_name }}{% endblocktrans %}{% endblock %} -{% block choose_button_label %}{% blocktrans %}Choose {{ snippet_type_name }}{% endblocktrans %}{% endblock %} diff --git a/wagtail/wagtailsnippets/widgets.py b/wagtail/wagtailsnippets/widgets.py index 7abf95a03..dcf73dafa 100644 --- a/wagtail/wagtailsnippets/widgets.py +++ b/wagtail/wagtailsnippets/widgets.py @@ -2,6 +2,8 @@ from __future__ import absolute_import, unicode_literals import json +from django.utils.translation import ugettext_lazy as _ + from wagtail.wagtailadmin.widgets import AdminChooser @@ -9,6 +11,11 @@ class AdminSnippetChooser(AdminChooser): target_content_type = None def __init__(self, content_type=None, **kwargs): + if 'snippet_type_name' in kwargs: + snippet_type_name = kwargs.pop('snippet_type_name') + self.choose_one_text = _('Choose %s') % snippet_type_name + self.choose_another_text = _('Choose another %s') % snippet_type_name + super(AdminSnippetChooser, self).__init__(**kwargs) if content_type is not None: self.target_content_type = content_type diff --git a/wagtail/wagtailusers/templates/wagtailusers/groups/includes/page_permissions_form.html b/wagtail/wagtailusers/templates/wagtailusers/groups/includes/page_permissions_form.html index 2521b11fe..57a270b99 100644 --- a/wagtail/wagtailusers/templates/wagtailusers/groups/includes/page_permissions_form.html +++ b/wagtail/wagtailusers/templates/wagtailusers/groups/includes/page_permissions_form.html @@ -1,13 +1,10 @@ {% load i18n %} - {% trans "Edit page" as choose_another_text_str %} - {% trans "Choose page" as choose_one_text_str %} - {% if form.instance.page %} - {% include "wagtailadmin/edit_handlers/page_chooser_panel.html" with field=form.page page=form.instance.page is_chosen=True choose_one_text_str=choose_one_text_str choose_another_text_str=choose_another_text_str only %} + {% include "wagtailadmin/edit_handlers/page_chooser_panel.html" with field=form.page page=form.instance.page is_chosen=True only %} {% else %} - {% include "wagtailadmin/edit_handlers/page_chooser_panel.html" with field=form.page is_chosen=False choose_one_text_str=choose_one_text_str choose_another_text_str=choose_another_text_str only %} + {% include "wagtailadmin/edit_handlers/page_chooser_panel.html" with field=form.page is_chosen=False only %} {% endif %} From 55c585d03e411e3b1b8cb3dff3455d29810c4581 Mon Sep 17 00:00:00 2001 From: Matt Westcott Date: Fri, 6 Feb 2015 15:52:40 +0000 Subject: [PATCH 23/40] Update *_chooser_panel.html templates so that they don't have to be passed an is_chosen flag --- wagtail/wagtailadmin/edit_handlers.py | 2 +- .../templates/wagtailadmin/edit_handlers/chooser_panel.html | 2 +- wagtail/wagtailadmin/templates/wagtailadmin/pages/copy.html | 2 +- .../editorspicks/includes/editorspicks_form.html | 6 +----- wagtail/wagtailsites/templates/wagtailsites/create.html | 6 +----- wagtail/wagtailsites/templates/wagtailsites/edit.html | 6 +----- wagtail/wagtailsnippets/edit_handlers.py | 4 +--- .../edit_handlers/snippet_chooser_panel.html | 2 +- .../wagtailusers/groups/includes/page_permissions_form.html | 6 +----- 9 files changed, 9 insertions(+), 27 deletions(-) diff --git a/wagtail/wagtailadmin/edit_handlers.py b/wagtail/wagtailadmin/edit_handlers.py index 8aa047fc5..35c404264 100644 --- a/wagtail/wagtailadmin/edit_handlers.py +++ b/wagtail/wagtailadmin/edit_handlers.py @@ -499,7 +499,7 @@ class BaseChooserPanel(BaseFieldPanel): context = { 'field': self.bound_field, self.object_type_name: instance_obj, - 'is_chosen': bool(instance_obj), + 'is_chosen': bool(instance_obj), # DEPRECATED - passed to templates for backwards compatibility only } return mark_safe(render_to_string(self.field_template, context)) diff --git a/wagtail/wagtailadmin/templates/wagtailadmin/edit_handlers/chooser_panel.html b/wagtail/wagtailadmin/templates/wagtailadmin/edit_handlers/chooser_panel.html index 65a627479..a3073f037 100644 --- a/wagtail/wagtailadmin/templates/wagtailadmin/edit_handlers/chooser_panel.html +++ b/wagtail/wagtailadmin/templates/wagtailadmin/edit_handlers/chooser_panel.html @@ -10,7 +10,7 @@ {% block form_field %} -
      +
      {% block chosen_state_view %}{% endblock %} diff --git a/wagtail/wagtailadmin/templates/wagtailadmin/pages/copy.html b/wagtail/wagtailadmin/templates/wagtailadmin/pages/copy.html index 26f3196cb..a7751ebc2 100644 --- a/wagtail/wagtailadmin/templates/wagtailadmin/pages/copy.html +++ b/wagtail/wagtailadmin/templates/wagtailadmin/pages/copy.html @@ -15,7 +15,7 @@ {% include "wagtailadmin/shared/field_as_li.html" with field=form.new_slug %}
    • - {% include "wagtailadmin/edit_handlers/page_chooser_panel.html" with field=form.new_parent_page page=parent_page is_chosen=True only %} + {% include "wagtailadmin/edit_handlers/page_chooser_panel.html" with field=form.new_parent_page page=parent_page only %}
    • {% if form.copy_subpages %} diff --git a/wagtail/wagtailsearch/templates/wagtailsearch/editorspicks/includes/editorspicks_form.html b/wagtail/wagtailsearch/templates/wagtailsearch/editorspicks/includes/editorspicks_form.html index 64fbbd724..ea023d352 100644 --- a/wagtail/wagtailsearch/templates/wagtailsearch/editorspicks/includes/editorspicks_form.html +++ b/wagtail/wagtailsearch/templates/wagtailsearch/editorspicks/includes/editorspicks_form.html @@ -10,11 +10,7 @@ {% trans "Promoted search result" %}
      • - {% if form.instance.page %} - {% include "wagtailadmin/edit_handlers/page_chooser_panel.html" with field=form.page page=form.instance.page is_chosen=True only %} - {% else %} - {% include "wagtailadmin/edit_handlers/page_chooser_panel.html" with field=form.page is_chosen=False only %} - {% endif %} + {% include "wagtailadmin/edit_handlers/page_chooser_panel.html" with field=form.page page=form.instance.page only %}
      • {% include "wagtailadmin/shared/field.html" with field=form.description only %} diff --git a/wagtail/wagtailsites/templates/wagtailsites/create.html b/wagtail/wagtailsites/templates/wagtailsites/create.html index fc8aae711..ce71534f1 100644 --- a/wagtail/wagtailsites/templates/wagtailsites/create.html +++ b/wagtail/wagtailsites/templates/wagtailsites/create.html @@ -17,11 +17,7 @@ {% include "wagtailadmin/shared/field_as_li.html" with field=form.port %}
      • - {% if form.instance.root_page %} - {% include "wagtailadmin/edit_handlers/page_chooser_panel.html" with field=form.root_page page=form.instance.root_page is_chosen=True only %} - {% else %} - {% include "wagtailadmin/edit_handlers/page_chooser_panel.html" with field=form.root_page is_chosen=False only %} - {% endif %} + {% include "wagtailadmin/edit_handlers/page_chooser_panel.html" with field=form.root_page page=form.instance.root_page only %}
      • {% include "wagtailadmin/shared/field_as_li.html" with field=form.is_default_site %} diff --git a/wagtail/wagtailsites/templates/wagtailsites/edit.html b/wagtail/wagtailsites/templates/wagtailsites/edit.html index 5125e4423..aa1563586 100644 --- a/wagtail/wagtailsites/templates/wagtailsites/edit.html +++ b/wagtail/wagtailsites/templates/wagtailsites/edit.html @@ -18,11 +18,7 @@ {% include "wagtailadmin/shared/field_as_li.html" with field=form.port %}
      • - {% if form.instance.root_page %} - {% include "wagtailadmin/edit_handlers/page_chooser_panel.html" with field=form.root_page page=form.instance.root_page is_chosen=True only %} - {% else %} - {% include "wagtailadmin/edit_handlers/page_chooser_panel.html" with field=form.root_page is_chosen=False only %} - {% endif %} + {% include "wagtailadmin/edit_handlers/page_chooser_panel.html" with field=form.root_page page=form.instance.root_page only %}
      • {% include "wagtailadmin/shared/field_as_li.html" with field=form.is_default_site %} diff --git a/wagtail/wagtailsnippets/edit_handlers.py b/wagtail/wagtailsnippets/edit_handlers.py index 6f23d6ba3..3490f6a6f 100644 --- a/wagtail/wagtailsnippets/edit_handlers.py +++ b/wagtail/wagtailsnippets/edit_handlers.py @@ -28,14 +28,12 @@ class BaseSnippetChooserPanel(BaseChooserPanel): return cls._content_type - def render_as_field(self, show_help_text=True): + def render_as_field(self): instance_obj = self.get_chosen_item() return mark_safe(render_to_string(self.field_template, { 'field': self.bound_field, self.object_type_name: instance_obj, 'snippet_type_name': self.snippet_type_name, - 'is_chosen': bool(instance_obj), - 'show_help_text': show_help_text, })) diff --git a/wagtail/wagtailsnippets/templates/wagtailsnippets/edit_handlers/snippet_chooser_panel.html b/wagtail/wagtailsnippets/templates/wagtailsnippets/edit_handlers/snippet_chooser_panel.html index 1dc2c40eb..0249e930a 100644 --- a/wagtail/wagtailsnippets/templates/wagtailsnippets/edit_handlers/snippet_chooser_panel.html +++ b/wagtail/wagtailsnippets/templates/wagtailsnippets/edit_handlers/snippet_chooser_panel.html @@ -4,5 +4,5 @@ {% block chooser_class %}snippet-chooser{% endblock %} {% block chosen_state_view %} - {% if is_chosen %}{{ item }}{% endif %} + {{ item }} {% endblock %} diff --git a/wagtail/wagtailusers/templates/wagtailusers/groups/includes/page_permissions_form.html b/wagtail/wagtailusers/templates/wagtailusers/groups/includes/page_permissions_form.html index 57a270b99..1e6a5c389 100644 --- a/wagtail/wagtailusers/templates/wagtailusers/groups/includes/page_permissions_form.html +++ b/wagtail/wagtailusers/templates/wagtailusers/groups/includes/page_permissions_form.html @@ -1,11 +1,7 @@ {% load i18n %} - {% if form.instance.page %} - {% include "wagtailadmin/edit_handlers/page_chooser_panel.html" with field=form.page page=form.instance.page is_chosen=True only %} - {% else %} - {% include "wagtailadmin/edit_handlers/page_chooser_panel.html" with field=form.page is_chosen=False only %} - {% endif %} + {% include "wagtailadmin/edit_handlers/page_chooser_panel.html" with field=form.page page=form.instance.page only %} {% include "wagtailadmin/edit_handlers/field_panel_field.html" with field=form.permission_type only %} From f56d927be08ccba228163aac389c3fe6cbfee49f Mon Sep 17 00:00:00 2001 From: Matt Westcott Date: Fri, 6 Feb 2015 16:40:51 +0000 Subject: [PATCH 24/40] provide a render_html method on WidgetWithScript so that subclasses can override the HTML part of the rendering too --- wagtail/utils/widgets.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/wagtail/utils/widgets.py b/wagtail/utils/widgets.py index 8ae51ce6b..04fc0f0f8 100644 --- a/wagtail/utils/widgets.py +++ b/wagtail/utils/widgets.py @@ -5,16 +5,20 @@ from django.utils.safestring import mark_safe class WidgetWithScript(Widget): + def render_html(self, name, value, attrs): + """Render the HTML (non-JS) portion of the field markup""" + return super(WidgetWithScript, self).render(name, value, attrs) + def render(self, name, value, attrs=None): - widget = super(WidgetWithScript, self).render(name, value, attrs) + widget_html = self.render_html(name, value, attrs) final_attrs = self.build_attrs(attrs, name=name) id_ = final_attrs.get('id', None) if id_ is None: - return widget + return widget_html js = self.render_js_init(id_, name, value) - out = '{0}'.format(widget, js) + out = '{0}'.format(widget_html, js) return mark_safe(out) def render_js_init(self, id_, name, value): From 8f655cd74d6f5fe289eafa1810fb9a37b8fe41ca Mon Sep 17 00:00:00 2001 From: Matt Westcott Date: Fri, 6 Feb 2015 17:07:30 +0000 Subject: [PATCH 25/40] make WidgetWithScript explicitly fail in the absence of an ID attribute --- wagtail/utils/widgets.py | 12 +++++++----- wagtail/wagtailadmin/widgets.py | 9 +++++++++ 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/wagtail/utils/widgets.py b/wagtail/utils/widgets.py index 04fc0f0f8..cc52ba1c9 100644 --- a/wagtail/utils/widgets.py +++ b/wagtail/utils/widgets.py @@ -10,12 +10,14 @@ class WidgetWithScript(Widget): return super(WidgetWithScript, self).render(name, value, attrs) def render(self, name, value, attrs=None): - widget_html = self.render_html(name, value, attrs) + # no point trying to come up with sensible semantics for when 'id' is missing from attrs, + # so let's make sure it fails early in the process + try: + id_ = attrs['id'] + except KeyError, TypeError: + raise TypeError("WidgetWithScript cannot be rendered without an 'id' attribute") - final_attrs = self.build_attrs(attrs, name=name) - id_ = final_attrs.get('id', None) - if id_ is None: - return widget_html + widget_html = self.render_html(name, value, attrs) js = self.render_js_init(id_, name, value) out = '{0}'.format(widget_html, js) diff --git a/wagtail/wagtailadmin/widgets.py b/wagtail/wagtailadmin/widgets.py index 7bf92a7cd..702b10c79 100644 --- a/wagtail/wagtailadmin/widgets.py +++ b/wagtail/wagtailadmin/widgets.py @@ -6,6 +6,7 @@ from django.core.urlresolvers import reverse from django.forms import widgets from django.contrib.contenttypes.models import ContentType from django.utils.translation import ugettext_lazy as _ +from django.template.loader import render_to_string from wagtail.utils.widgets import WidgetWithScript from wagtail.wagtailcore.models import Page @@ -61,6 +62,14 @@ class AdminPageChooser(AdminChooser): super(AdminPageChooser, self).__init__(**kwargs) self.target_content_type = content_type or ContentType.objects.get_for_model(Page) + def render_html(self, name, value, attrs): + original_field_html = super(AdminPageChooser, self).render_html(name, value, attrs) + + return render_to_string("wagtailadmin/widgets/page_chooser.html", { + 'original_field_html': original_field_html, + 'widget': self, + }) + def render_js_init(self, id_, name, value): page = Page.objects.get(pk=value) if value else None parent = page.get_parent() if page else None From f4b1a3938a1f2a21d561114e15b2d886a320ecee Mon Sep 17 00:00:00 2001 From: benjaoming Date: Fri, 6 Feb 2015 21:28:34 -0800 Subject: [PATCH 26/40] Remove unused import Image Don't see this used anywhere...!? --- docs/core_components/pages/creating_pages.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/core_components/pages/creating_pages.rst b/docs/core_components/pages/creating_pages.rst index 24e598549..61bcf712d 100644 --- a/docs/core_components/pages/creating_pages.rst +++ b/docs/core_components/pages/creating_pages.rst @@ -20,7 +20,6 @@ This example represents a typical blog post: from wagtail.wagtailcore.fields import RichTextField from wagtail.wagtailadmin.edit_handlers import FieldPanel from wagtail.wagtailimages.edit_handlers import ImageChooserPanel - from wagtail.wagtailimages.models import Image class BlogPage(Page): body = RichTextField() From a8f53c4b03c28e36902220672f3066fc4cb26908 Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Sun, 8 Feb 2015 13:40:35 +0000 Subject: [PATCH 27/40] Added a failing test for #968 --- wagtail/wagtailimages/tests/test_image_operations.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/wagtail/wagtailimages/tests/test_image_operations.py b/wagtail/wagtailimages/tests/test_image_operations.py index f4dce9642..38d6be06c 100644 --- a/wagtail/wagtailimages/tests/test_image_operations.py +++ b/wagtail/wagtailimages/tests/test_image_operations.py @@ -151,6 +151,13 @@ class TestFillOperation(ImageOperationTestCase): ('resize', (800, 600), {}), ]), + # Basic usage with an oddly-sized original image + # This checks for a rounding precision issue (#968) + ('fill-200x200', Image(width=539, height=720), [ + ('crop', (0, 90, 539, 629), {}), + ('resize', (200, 200), {}), + ]), + # Closeness shouldn't have any effect when used without a focal point ('fill-800x600-c100', Image(width=1000, height=1000), [ ('crop', (0, 125, 1000, 875), {}), From b2b790e38756e25a222dc1b9a500a0f50b369ccb Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Sun, 8 Feb 2015 13:57:07 +0000 Subject: [PATCH 28/40] Improved precision of "fill" operation resizing Fixes #968 --- wagtail/wagtailimages/image_operations.py | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/wagtail/wagtailimages/image_operations.py b/wagtail/wagtailimages/image_operations.py index 3a7884a08..f71b7290a 100644 --- a/wagtail/wagtailimages/image_operations.py +++ b/wagtail/wagtailimages/image_operations.py @@ -158,22 +158,16 @@ class FillOperation(Operation): # Crop! willow.crop(int(left), int(top), int(right), int(bottom)) - # Resize the final image + # Get scale for resizing + # The scale should be the same for both the horizontal and + # vertical axes aftercrop_width, aftercrop_height = willow.get_size() - horz_scale = self.width / aftercrop_width - vert_scale = self.height / aftercrop_height + scale = self.width / aftercrop_width - if aftercrop_width <= self.width or aftercrop_height <= self.height: - return - - if horz_scale > vert_scale: - width = self.width - height = int(aftercrop_height * horz_scale) - else: - width = int(aftercrop_width * vert_scale) - height = self.height - - willow.resize(width, height) + # Only resize if the image is too big + if scale < 1.0: + # Resize! + willow.resize(self.width, self.height) def get_vary(self, image): focal_point = image.get_focal_point() From 357a5c7449f3a1f3d20ee9b091082d16f143d42f Mon Sep 17 00:00:00 2001 From: Alejandro Varas Date: Wed, 10 Sep 2014 12:32:26 -0300 Subject: [PATCH 29/40] Fixed TypeError raised by `richtext` template tag --- .../wagtailcore/templatetags/wagtailcore_tags.py | 4 +++- wagtail/wagtailcore/tests/tests.py | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/wagtail/wagtailcore/templatetags/wagtailcore_tags.py b/wagtail/wagtailcore/templatetags/wagtailcore_tags.py index b68a66d63..c3b660a16 100644 --- a/wagtail/wagtailcore/templatetags/wagtailcore_tags.py +++ b/wagtail/wagtailcore/templatetags/wagtailcore_tags.py @@ -35,4 +35,6 @@ def wagtail_version(): @register.filter def richtext(value): - return mark_safe('
        ' + expand_db_html(value) + '
        ') + if value: + return mark_safe('
        ' + expand_db_html(value) + '
        ') + return '' diff --git a/wagtail/wagtailcore/tests/tests.py b/wagtail/wagtailcore/tests/tests.py index c53494648..3531a35ae 100644 --- a/wagtail/wagtailcore/tests/tests.py +++ b/wagtail/wagtailcore/tests/tests.py @@ -4,6 +4,7 @@ from django.test import TestCase from django.core.cache import cache from wagtail.wagtailcore.models import Page, Site +from wagtail.wagtailcore.templatetags.wagtailcore_tags import richtext from wagtail.wagtailcore.utils import resolve_model_string from wagtail.tests.models import SimplePage @@ -184,3 +185,16 @@ class TestResolveModelString(TestCase): @unittest.expectedFailure # Raising LookupError instead def test_resolve_from_bad_type(self): self.assertRaises(ValueError, resolve_model_string, resolve_model_string) + + +class TestRichtextTag(TestCase): + + def test_typeerror(self): + """`richtext` fails when it's called with `value` being not a string + or buffer. + """ + value = None + + result = richtext(value) + + self.assertEqual(result, '') From 89bb3787e3b0ed99210ff4bd23b34ec32720e537 Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Mon, 9 Feb 2015 12:35:19 +0000 Subject: [PATCH 30/40] Improvements to #620 As per https://github.com/torchbox/wagtail/pull/620#issuecomment-59203932 Also improved the tests a little bit --- .../templatetags/wagtailcore_tags.py | 9 ++++++--- wagtail/wagtailcore/tests/tests.py | 17 ++++++++--------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/wagtail/wagtailcore/templatetags/wagtailcore_tags.py b/wagtail/wagtailcore/templatetags/wagtailcore_tags.py index c3b660a16..c0cf66e29 100644 --- a/wagtail/wagtailcore/templatetags/wagtailcore_tags.py +++ b/wagtail/wagtailcore/templatetags/wagtailcore_tags.py @@ -35,6 +35,9 @@ def wagtail_version(): @register.filter def richtext(value): - if value: - return mark_safe('
        ' + expand_db_html(value) + '
        ') - return '' + if value is not None: + html = expand_db_html(value) + else: + html = '' + + return mark_safe('
        ' + html + '
        ') diff --git a/wagtail/wagtailcore/tests/tests.py b/wagtail/wagtailcore/tests/tests.py index 3531a35ae..fd2e4de93 100644 --- a/wagtail/wagtailcore/tests/tests.py +++ b/wagtail/wagtailcore/tests/tests.py @@ -2,6 +2,7 @@ import unittest from django.test import TestCase from django.core.cache import cache +from django.utils.safestring import SafeString from wagtail.wagtailcore.models import Page, Site from wagtail.wagtailcore.templatetags.wagtailcore_tags import richtext @@ -188,13 +189,11 @@ class TestResolveModelString(TestCase): class TestRichtextTag(TestCase): + def test_call_with_text(self): + result = richtext("Hello world!") + self.assertEqual(result, '
        Hello world!
        ') + self.assertIsInstance(result, SafeString) - def test_typeerror(self): - """`richtext` fails when it's called with `value` being not a string - or buffer. - """ - value = None - - result = richtext(value) - - self.assertEqual(result, '') + def test_call_with_none(self): + result = richtext(None) + self.assertEqual(result, '
        ') From d4ab7e833fdb043d2b5fdff5c0ed68582af0fe13 Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Mon, 9 Feb 2015 12:39:12 +0000 Subject: [PATCH 31/40] Changelog, release notes and contributor entry for #620 --- CHANGELOG.txt | 1 + CONTRIBUTORS.rst | 1 + docs/releases/0.8.5.rst | 1 + 3 files changed, 3 insertions(+) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 2e2977ab4..c60f672d2 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -34,6 +34,7 @@ Changelog * Fix: Storage backends that return raw ContentFile objects are now handled correctly when resizing images (@georgewhewell) * Fix: Punctuation characters are no longer stripped when performing search queries * Fix: When adding tags where there were none before, it is now possible to save a single tag with multiple words in it +* Fix: richtext template tag no longer raises TypeError if None is passed into it (Alejandro Varas) 0.8.4 (04.12.2014) ~~~~~~~~~~~~~~~~~~ diff --git a/CONTRIBUTORS.rst b/CONTRIBUTORS.rst index d0c34417c..44992e71a 100644 --- a/CONTRIBUTORS.rst +++ b/CONTRIBUTORS.rst @@ -42,6 +42,7 @@ Contributors * georgewhewell * Frank Wiles * Sebastian Spiegel +* Alejandro Varas Translators =========== diff --git a/docs/releases/0.8.5.rst b/docs/releases/0.8.5.rst index f75f93e60..482d660a0 100644 --- a/docs/releases/0.8.5.rst +++ b/docs/releases/0.8.5.rst @@ -20,3 +20,4 @@ Bug fixes * Storage backends that return raw ContentFile objects are now handled correctly when resizing images * Punctuation characters are no longer stripped when performing search queries * When adding tags where there were none before, it is now possible to save a single tag with multiple words in it + * ``richtext`` template tag no longer raises ``TypeError`` if ``None`` is passed into it From 6e2faa0b66fd85d470a5e51fa98e94456340630f Mon Sep 17 00:00:00 2001 From: Matt Westcott Date: Mon, 9 Feb 2015 18:26:35 +0000 Subject: [PATCH 32/40] Move the page chooser HTML markup from page_chooser_panel.html entirely within the AdminPageChooser widget's render() method --- .../edit_handlers/page_chooser_panel.html | 7 ++--- .../wagtailadmin/widgets/chooser.html | 29 +++++++++++++++++++ .../wagtailadmin/widgets/page_chooser.html | 5 ++++ wagtail/wagtailadmin/widgets.py | 18 +++++++++++- 4 files changed, 53 insertions(+), 6 deletions(-) create mode 100644 wagtail/wagtailadmin/templates/wagtailadmin/widgets/chooser.html create mode 100644 wagtail/wagtailadmin/templates/wagtailadmin/widgets/page_chooser.html diff --git a/wagtail/wagtailadmin/templates/wagtailadmin/edit_handlers/page_chooser_panel.html b/wagtail/wagtailadmin/templates/wagtailadmin/edit_handlers/page_chooser_panel.html index 800d40e65..165bca017 100644 --- a/wagtail/wagtailadmin/templates/wagtailadmin/edit_handlers/page_chooser_panel.html +++ b/wagtail/wagtailadmin/templates/wagtailadmin/edit_handlers/page_chooser_panel.html @@ -1,5 +1,2 @@ -{% extends "wagtailadmin/edit_handlers/chooser_panel.html" %} - -{% block chosen_state_view %} - {{ page.title }} -{% endblock %} +{# Page chooser is now implemented as an entirely standard form widget - page_chooser_panel.html is redundant #} +{% include "wagtailadmin/shared/field.html" %} diff --git a/wagtail/wagtailadmin/templates/wagtailadmin/widgets/chooser.html b/wagtail/wagtailadmin/templates/wagtailadmin/widgets/chooser.html new file mode 100644 index 000000000..cc5e9218f --- /dev/null +++ b/wagtail/wagtailadmin/templates/wagtailadmin/widgets/chooser.html @@ -0,0 +1,29 @@ +{% load i18n %} +{% comment %} + Either the chosen or unchosen div will be shown, depending on the presence + of the 'blank' class on the container. + + Any element with the 'action-choose' class will open the page chooser modal + when clicked. +{% endcomment %} + +
        + +
        + {% block chosen_state_view %}{% endblock %} + +
        + {% if not widget.is_required %} + + {% endif %} + +
        +
        + +
        + +
        + +
        + +{{ original_field_html }} diff --git a/wagtail/wagtailadmin/templates/wagtailadmin/widgets/page_chooser.html b/wagtail/wagtailadmin/templates/wagtailadmin/widgets/page_chooser.html new file mode 100644 index 000000000..487cce366 --- /dev/null +++ b/wagtail/wagtailadmin/templates/wagtailadmin/widgets/page_chooser.html @@ -0,0 +1,5 @@ +{% extends "wagtailadmin/widgets/chooser.html" %} + +{% block chosen_state_view %} + {{ page.title }} +{% endblock %} diff --git a/wagtail/wagtailadmin/widgets.py b/wagtail/wagtailadmin/widgets.py index 702b10c79..e53bfb5c1 100644 --- a/wagtail/wagtailadmin/widgets.py +++ b/wagtail/wagtailadmin/widgets.py @@ -42,6 +42,16 @@ class AdminChooser(WidgetWithScript, widgets.Input): choose_another_text = _("Choose another item") clear_choice_text = _("Clear choice") + def get_instance(self, model_class, value): + # helper method for cleanly turning 'value' into an instance object + if value is None: + return None + + try: + return model_class.objects.get(pk=value) + except model_class.DoesNotExist: + return None + def __init__(self, **kwargs): # allow choose_one_text / choose_another_text to be overridden per-instance if 'choose_one_text' in kwargs: @@ -65,9 +75,15 @@ class AdminPageChooser(AdminChooser): def render_html(self, name, value, attrs): original_field_html = super(AdminPageChooser, self).render_html(name, value, attrs) + model_class = self.target_content_type.model_class() + instance = self.get_instance(model_class, value) + return render_to_string("wagtailadmin/widgets/page_chooser.html", { - 'original_field_html': original_field_html, 'widget': self, + 'original_field_html': original_field_html, + 'attrs': attrs, + 'value': value, + 'page': instance, }) def render_js_init(self, id_, name, value): From fe797437e79086e22c6bfca4c65fcefb513ec488 Mon Sep 17 00:00:00 2001 From: Matt Westcott Date: Mon, 9 Feb 2015 18:47:11 +0000 Subject: [PATCH 33/40] Remove now-redundant references to page_chooser_panel.html --- .../wagtailstyleguide/templates/wagtailstyleguide/base.html | 2 -- wagtail/wagtailadmin/edit_handlers.py | 3 +-- wagtail/wagtailadmin/templates/wagtailadmin/pages/copy.html | 5 +---- wagtail/wagtailadmin/views/pages.py | 1 - .../editorspicks/includes/editorspicks_form.html | 2 +- wagtail/wagtailsites/templates/wagtailsites/create.html | 6 +----- wagtail/wagtailsites/templates/wagtailsites/edit.html | 6 +----- .../wagtailusers/groups/includes/page_permissions_form.html | 2 +- 8 files changed, 6 insertions(+), 21 deletions(-) diff --git a/wagtail/contrib/wagtailstyleguide/templates/wagtailstyleguide/base.html b/wagtail/contrib/wagtailstyleguide/templates/wagtailstyleguide/base.html index de0019f84..c0288caca 100644 --- a/wagtail/contrib/wagtailstyleguide/templates/wagtailstyleguide/base.html +++ b/wagtail/contrib/wagtailstyleguide/templates/wagtailstyleguide/base.html @@ -347,8 +347,6 @@ {% for field in example_form %} {% if field.name == 'file' %} {% include "wagtailimages/images/_file_field.html" %} - {% elif field.name == 'page_chooser' %} -
      • {% include "wagtailadmin/edit_handlers/page_chooser_panel.html" with field=field only %}
      • {% elif field.name == 'image_chooser' %}
      • {% include "wagtailimages/edit_handlers/image_chooser_panel.html" with field=field only %}
      • {% elif field.name == 'document_chooser' %} diff --git a/wagtail/wagtailadmin/edit_handlers.py b/wagtail/wagtailadmin/edit_handlers.py index 35c404264..19b5d6a27 100644 --- a/wagtail/wagtailadmin/edit_handlers.py +++ b/wagtail/wagtailadmin/edit_handlers.py @@ -480,7 +480,7 @@ class BaseChooserPanel(BaseFieldPanel): a hidden foreign key input. Subclasses provide: - * field_template + * field_template (only required if the default template of field_panel_field.html is not usable) * object_type_name - something like 'image' which will be used as the var name for the object instance in the field_template """ @@ -505,7 +505,6 @@ class BaseChooserPanel(BaseFieldPanel): class BasePageChooserPanel(BaseChooserPanel): - field_template = "wagtailadmin/edit_handlers/page_chooser_panel.html" object_type_name = "page" _target_content_type = None diff --git a/wagtail/wagtailadmin/templates/wagtailadmin/pages/copy.html b/wagtail/wagtailadmin/templates/wagtailadmin/pages/copy.html index a7751ebc2..b0ccf3397 100644 --- a/wagtail/wagtailadmin/templates/wagtailadmin/pages/copy.html +++ b/wagtail/wagtailadmin/templates/wagtailadmin/pages/copy.html @@ -13,10 +13,7 @@
          {% include "wagtailadmin/shared/field_as_li.html" with field=form.new_title %} {% include "wagtailadmin/shared/field_as_li.html" with field=form.new_slug %} - -
        • - {% include "wagtailadmin/edit_handlers/page_chooser_panel.html" with field=form.new_parent_page page=parent_page only %} -
        • + {% include "wagtailadmin/shared/field_as_li.html" with field=form.new_parent_page %} {% if form.copy_subpages %} {% include "wagtailadmin/shared/field_as_li.html" with field=form.copy_subpages %} diff --git a/wagtail/wagtailadmin/views/pages.py b/wagtail/wagtailadmin/views/pages.py index b5e05ac4f..a9c5c6fe5 100644 --- a/wagtail/wagtailadmin/views/pages.py +++ b/wagtail/wagtailadmin/views/pages.py @@ -698,7 +698,6 @@ def copy(request, page_id): return render(request, 'wagtailadmin/pages/copy.html', { 'page': page, - 'parent_page': parent_page, 'form': form, }) diff --git a/wagtail/wagtailsearch/templates/wagtailsearch/editorspicks/includes/editorspicks_form.html b/wagtail/wagtailsearch/templates/wagtailsearch/editorspicks/includes/editorspicks_form.html index ea023d352..65c8c2f1d 100644 --- a/wagtail/wagtailsearch/templates/wagtailsearch/editorspicks/includes/editorspicks_form.html +++ b/wagtail/wagtailsearch/templates/wagtailsearch/editorspicks/includes/editorspicks_form.html @@ -10,7 +10,7 @@ {% trans "Promoted search result" %}
          • - {% include "wagtailadmin/edit_handlers/page_chooser_panel.html" with field=form.page page=form.instance.page only %} + {% include "wagtailadmin/shared/field.html" with field=form.page only %}
          • {% include "wagtailadmin/shared/field.html" with field=form.description only %} diff --git a/wagtail/wagtailsites/templates/wagtailsites/create.html b/wagtail/wagtailsites/templates/wagtailsites/create.html index ce71534f1..8a94b372a 100644 --- a/wagtail/wagtailsites/templates/wagtailsites/create.html +++ b/wagtail/wagtailsites/templates/wagtailsites/create.html @@ -15,11 +15,7 @@
              {% include "wagtailadmin/shared/field_as_li.html" with field=form.hostname %} {% include "wagtailadmin/shared/field_as_li.html" with field=form.port %} - -
            • - {% include "wagtailadmin/edit_handlers/page_chooser_panel.html" with field=form.root_page page=form.instance.root_page only %} -
            • - + {% include "wagtailadmin/shared/field_as_li.html" with field=form.root_page %} {% include "wagtailadmin/shared/field_as_li.html" with field=form.is_default_site %}
            • diff --git a/wagtail/wagtailsites/templates/wagtailsites/edit.html b/wagtail/wagtailsites/templates/wagtailsites/edit.html index aa1563586..c1b2c31e2 100644 --- a/wagtail/wagtailsites/templates/wagtailsites/edit.html +++ b/wagtail/wagtailsites/templates/wagtailsites/edit.html @@ -16,11 +16,7 @@
                {% include "wagtailadmin/shared/field_as_li.html" with field=form.hostname %} {% include "wagtailadmin/shared/field_as_li.html" with field=form.port %} - -
              • - {% include "wagtailadmin/edit_handlers/page_chooser_panel.html" with field=form.root_page page=form.instance.root_page only %} -
              • - + {% include "wagtailadmin/shared/field_as_li.html" with field=form.root_page %} {% include "wagtailadmin/shared/field_as_li.html" with field=form.is_default_site %}
              • diff --git a/wagtail/wagtailusers/templates/wagtailusers/groups/includes/page_permissions_form.html b/wagtail/wagtailusers/templates/wagtailusers/groups/includes/page_permissions_form.html index 1e6a5c389..f6f56414d 100644 --- a/wagtail/wagtailusers/templates/wagtailusers/groups/includes/page_permissions_form.html +++ b/wagtail/wagtailusers/templates/wagtailusers/groups/includes/page_permissions_form.html @@ -1,7 +1,7 @@ {% load i18n %} - {% include "wagtailadmin/edit_handlers/page_chooser_panel.html" with field=form.page page=form.instance.page only %} + {% include "wagtailadmin/edit_handlers/field_panel_field.html" with field=form.page only %} {% include "wagtailadmin/edit_handlers/field_panel_field.html" with field=form.permission_type only %} From 41577759a1151fedf4227f121f3f5ee40233027e Mon Sep 17 00:00:00 2001 From: Matt Westcott Date: Mon, 9 Feb 2015 18:58:17 +0000 Subject: [PATCH 34/40] Move the document chooser HTML markup from document_chooser_panel.html entirely within the AdminDocumentChooser widget's render() method --- .../templates/wagtailstyleguide/base.html | 2 -- wagtail/wagtaildocs/edit_handlers.py | 1 - .../edit_handlers/document_chooser_panel.html | 9 ++------- .../wagtaildocs/widgets/document_chooser.html | 6 ++++++ wagtail/wagtaildocs/widgets.py | 15 +++++++++++++++ 5 files changed, 23 insertions(+), 10 deletions(-) create mode 100644 wagtail/wagtaildocs/templates/wagtaildocs/widgets/document_chooser.html diff --git a/wagtail/contrib/wagtailstyleguide/templates/wagtailstyleguide/base.html b/wagtail/contrib/wagtailstyleguide/templates/wagtailstyleguide/base.html index c0288caca..b16bc445c 100644 --- a/wagtail/contrib/wagtailstyleguide/templates/wagtailstyleguide/base.html +++ b/wagtail/contrib/wagtailstyleguide/templates/wagtailstyleguide/base.html @@ -349,8 +349,6 @@ {% include "wagtailimages/images/_file_field.html" %} {% elif field.name == 'image_chooser' %}
              • {% include "wagtailimages/edit_handlers/image_chooser_panel.html" with field=field only %}
              • - {% elif field.name == 'document_chooser' %} -
              • {% include "wagtaildocs/edit_handlers/document_chooser_panel.html" with field=field only %}
              • {% else %} {% include "wagtailadmin/shared/field_as_li.html" %} {% endif %} diff --git a/wagtail/wagtaildocs/edit_handlers.py b/wagtail/wagtaildocs/edit_handlers.py index 70f562847..53b752f1c 100644 --- a/wagtail/wagtaildocs/edit_handlers.py +++ b/wagtail/wagtaildocs/edit_handlers.py @@ -5,7 +5,6 @@ from .widgets import AdminDocumentChooser class BaseDocumentChooserPanel(BaseChooserPanel): - field_template = "wagtaildocs/edit_handlers/document_chooser_panel.html" object_type_name = "document" @classmethod diff --git a/wagtail/wagtaildocs/templates/wagtaildocs/edit_handlers/document_chooser_panel.html b/wagtail/wagtaildocs/templates/wagtaildocs/edit_handlers/document_chooser_panel.html index 59dc2ed2a..4ea2a3d7a 100644 --- a/wagtail/wagtaildocs/templates/wagtaildocs/edit_handlers/document_chooser_panel.html +++ b/wagtail/wagtaildocs/templates/wagtaildocs/edit_handlers/document_chooser_panel.html @@ -1,7 +1,2 @@ -{% extends "wagtailadmin/edit_handlers/chooser_panel.html" %} -{% load i18n %} -{% block chooser_class %}document-chooser{% endblock %} - -{% block chosen_state_view %} - {{ document.title }} -{% endblock %} +{# Document chooser is now implemented as an entirely standard form widget - document_chooser_panel.html is redundant #} +{% include "wagtailadmin/shared/field.html" %} diff --git a/wagtail/wagtaildocs/templates/wagtaildocs/widgets/document_chooser.html b/wagtail/wagtaildocs/templates/wagtaildocs/widgets/document_chooser.html new file mode 100644 index 000000000..ac023728a --- /dev/null +++ b/wagtail/wagtaildocs/templates/wagtaildocs/widgets/document_chooser.html @@ -0,0 +1,6 @@ +{% extends "wagtailadmin/widgets/chooser.html" %} +{% block chooser_class %}document-chooser{% endblock %} + +{% block chosen_state_view %} + {{ document.title }} +{% endblock %} diff --git a/wagtail/wagtaildocs/widgets.py b/wagtail/wagtaildocs/widgets.py index e5d490f51..73267b539 100644 --- a/wagtail/wagtaildocs/widgets.py +++ b/wagtail/wagtaildocs/widgets.py @@ -2,14 +2,29 @@ from __future__ import absolute_import, unicode_literals import json +from django.template.loader import render_to_string from django.utils.translation import ugettext_lazy as _ from wagtail.wagtailadmin.widgets import AdminChooser +from wagtail.wagtaildocs.models import Document class AdminDocumentChooser(AdminChooser): choose_one_text = _('Choose a document') choose_another_text = _('Choose another document') + def render_html(self, name, value, attrs): + original_field_html = super(AdminDocumentChooser, self).render_html(name, value, attrs) + + instance = self.get_instance(Document, value) + + return render_to_string("wagtaildocs/widgets/document_chooser.html", { + 'widget': self, + 'original_field_html': original_field_html, + 'attrs': attrs, + 'value': value, + 'document': instance, + }) + def render_js_init(self, id_, name, value): return "createDocumentChooser({0});".format(json.dumps(id_)) From 435e4571b325f273560e8eafb26673da8c76f099 Mon Sep 17 00:00:00 2001 From: Matt Westcott Date: Mon, 9 Feb 2015 19:08:12 +0000 Subject: [PATCH 35/40] Move the image chooser HTML markup from image_chooser_panel.html entirely within the AdminImageChooser widget's render() method --- .../templates/wagtailstyleguide/base.html | 2 -- wagtail/wagtailimages/edit_handlers.py | 1 - .../edit_handlers/image_chooser_panel.html | 17 ++--------------- .../wagtailimages/widgets/image_chooser.html | 14 ++++++++++++++ wagtail/wagtailimages/widgets.py | 19 +++++++++++++++++++ 5 files changed, 35 insertions(+), 18 deletions(-) create mode 100644 wagtail/wagtailimages/templates/wagtailimages/widgets/image_chooser.html diff --git a/wagtail/contrib/wagtailstyleguide/templates/wagtailstyleguide/base.html b/wagtail/contrib/wagtailstyleguide/templates/wagtailstyleguide/base.html index b16bc445c..1124aae97 100644 --- a/wagtail/contrib/wagtailstyleguide/templates/wagtailstyleguide/base.html +++ b/wagtail/contrib/wagtailstyleguide/templates/wagtailstyleguide/base.html @@ -347,8 +347,6 @@ {% for field in example_form %} {% if field.name == 'file' %} {% include "wagtailimages/images/_file_field.html" %} - {% elif field.name == 'image_chooser' %} -
              • {% include "wagtailimages/edit_handlers/image_chooser_panel.html" with field=field only %}
              • {% else %} {% include "wagtailadmin/shared/field_as_li.html" %} {% endif %} diff --git a/wagtail/wagtailimages/edit_handlers.py b/wagtail/wagtailimages/edit_handlers.py index 687d3b64a..8cdba8cba 100644 --- a/wagtail/wagtailimages/edit_handlers.py +++ b/wagtail/wagtailimages/edit_handlers.py @@ -5,7 +5,6 @@ from .widgets import AdminImageChooser class BaseImageChooserPanel(BaseChooserPanel): - field_template = "wagtailimages/edit_handlers/image_chooser_panel.html" object_type_name = "image" @classmethod diff --git a/wagtail/wagtailimages/templates/wagtailimages/edit_handlers/image_chooser_panel.html b/wagtail/wagtailimages/templates/wagtailimages/edit_handlers/image_chooser_panel.html index 38df1be80..dc3ecf1bf 100644 --- a/wagtail/wagtailimages/templates/wagtailimages/edit_handlers/image_chooser_panel.html +++ b/wagtail/wagtailimages/templates/wagtailimages/edit_handlers/image_chooser_panel.html @@ -1,15 +1,2 @@ -{% extends "wagtailadmin/edit_handlers/chooser_panel.html" %} -{% load wagtailimages_tags %} -{% load i18n %} - -{% block chooser_class %}image-chooser{% endblock %} - -{% block chosen_state_view %} -
                - {% if image %} - {% image image max-130x130 %} - {% else %} - - {% endif %} -
                -{% endblock %} +{# Image chooser is now implemented as an entirely standard form widget - image_chooser_panel.html is redundant #} +{% include "wagtailadmin/shared/field.html" %} diff --git a/wagtail/wagtailimages/templates/wagtailimages/widgets/image_chooser.html b/wagtail/wagtailimages/templates/wagtailimages/widgets/image_chooser.html new file mode 100644 index 000000000..428b12247 --- /dev/null +++ b/wagtail/wagtailimages/templates/wagtailimages/widgets/image_chooser.html @@ -0,0 +1,14 @@ +{% extends "wagtailadmin/widgets/chooser.html" %} +{% load wagtailimages_tags %} + +{% block chooser_class %}image-chooser{% endblock %} + +{% block chosen_state_view %} +
                + {% if image %} + {% image image max-130x130 %} + {% else %} + + {% endif %} +
                +{% endblock %} diff --git a/wagtail/wagtailimages/widgets.py b/wagtail/wagtailimages/widgets.py index 4bce83505..e628ed4e9 100644 --- a/wagtail/wagtailimages/widgets.py +++ b/wagtail/wagtailimages/widgets.py @@ -2,9 +2,11 @@ from __future__ import absolute_import, unicode_literals import json +from django.template.loader import render_to_string from django.utils.translation import ugettext_lazy as _ from wagtail.wagtailadmin.widgets import AdminChooser +from wagtail.wagtailimages.models import get_image_model class AdminImageChooser(AdminChooser): @@ -12,5 +14,22 @@ class AdminImageChooser(AdminChooser): choose_another_text = _('Choose another image') clear_choice_text = _('Clear image') + def __init__(self, **kwargs): + super(AdminImageChooser, self).__init__(**kwargs) + self.image_model = get_image_model() + + def render_html(self, name, value, attrs): + original_field_html = super(AdminImageChooser, self).render_html(name, value, attrs) + + instance = self.get_instance(self.image_model, value) + + return render_to_string("wagtailimages/widgets/image_chooser.html", { + 'widget': self, + 'original_field_html': original_field_html, + 'attrs': attrs, + 'value': value, + 'image': instance, + }) + def render_js_init(self, id_, name, value): return "createImageChooser({0});".format(json.dumps(id_)) From 63dafbe4b77ede7e58e3dd6526b395ea94eac4bc Mon Sep 17 00:00:00 2001 From: Matt Westcott Date: Mon, 9 Feb 2015 19:18:58 +0000 Subject: [PATCH 36/40] Move the snippet chooser HTML markup from snippet_chooser_panel.html entirely within the AdminSnippetChooser widget's render() method --- wagtail/wagtailsnippets/edit_handlers.py | 1 - .../edit_handlers/snippet_chooser_panel.html | 10 ++-------- .../wagtailsnippets/widgets/snippet_chooser.html | 7 +++++++ wagtail/wagtailsnippets/widgets.py | 15 +++++++++++++++ 4 files changed, 24 insertions(+), 9 deletions(-) create mode 100644 wagtail/wagtailsnippets/templates/wagtailsnippets/widgets/snippet_chooser.html diff --git a/wagtail/wagtailsnippets/edit_handlers.py b/wagtail/wagtailsnippets/edit_handlers.py index 3490f6a6f..0c3f26564 100644 --- a/wagtail/wagtailsnippets/edit_handlers.py +++ b/wagtail/wagtailsnippets/edit_handlers.py @@ -10,7 +10,6 @@ from .widgets import AdminSnippetChooser class BaseSnippetChooserPanel(BaseChooserPanel): - field_template = "wagtailsnippets/edit_handlers/snippet_chooser_panel.html" object_type_name = 'item' _content_type = None diff --git a/wagtail/wagtailsnippets/templates/wagtailsnippets/edit_handlers/snippet_chooser_panel.html b/wagtail/wagtailsnippets/templates/wagtailsnippets/edit_handlers/snippet_chooser_panel.html index 0249e930a..83babb1ab 100644 --- a/wagtail/wagtailsnippets/templates/wagtailsnippets/edit_handlers/snippet_chooser_panel.html +++ b/wagtail/wagtailsnippets/templates/wagtailsnippets/edit_handlers/snippet_chooser_panel.html @@ -1,8 +1,2 @@ -{% extends "wagtailadmin/edit_handlers/chooser_panel.html" %} -{% load i18n %} - -{% block chooser_class %}snippet-chooser{% endblock %} - -{% block chosen_state_view %} - {{ item }} -{% endblock %} +{# Snippet chooser is now implemented as an entirely standard form widget - snippet_chooser_panel.html is redundant #} +{% include "wagtailadmin/shared/field.html" %} diff --git a/wagtail/wagtailsnippets/templates/wagtailsnippets/widgets/snippet_chooser.html b/wagtail/wagtailsnippets/templates/wagtailsnippets/widgets/snippet_chooser.html new file mode 100644 index 000000000..b46f3dbdc --- /dev/null +++ b/wagtail/wagtailsnippets/templates/wagtailsnippets/widgets/snippet_chooser.html @@ -0,0 +1,7 @@ +{% extends "wagtailadmin/widgets/chooser.html" %} + +{% block chooser_class %}snippet-chooser{% endblock %} + +{% block chosen_state_view %} + {{ item }} +{% endblock %} diff --git a/wagtail/wagtailsnippets/widgets.py b/wagtail/wagtailsnippets/widgets.py index dcf73dafa..611efc40f 100644 --- a/wagtail/wagtailsnippets/widgets.py +++ b/wagtail/wagtailsnippets/widgets.py @@ -2,6 +2,7 @@ from __future__ import absolute_import, unicode_literals import json +from django.template.loader import render_to_string from django.utils.translation import ugettext_lazy as _ from wagtail.wagtailadmin.widgets import AdminChooser @@ -20,6 +21,20 @@ class AdminSnippetChooser(AdminChooser): if content_type is not None: self.target_content_type = content_type + def render_html(self, name, value, attrs): + original_field_html = super(AdminSnippetChooser, self).render_html(name, value, attrs) + + model_class = self.target_content_type.model_class() + instance = self.get_instance(model_class, value) + + return render_to_string("wagtailsnippets/widgets/snippet_chooser.html", { + 'widget': self, + 'original_field_html': original_field_html, + 'attrs': attrs, + 'value': value, + 'item': instance, + }) + def render_js_init(self, id_, name, value): content_type = self.target_content_type From 13e1811c544b8694408b0b40740e4ade935eae4a Mon Sep 17 00:00:00 2001 From: Matt Westcott Date: Mon, 9 Feb 2015 19:34:18 +0000 Subject: [PATCH 37/40] mark chooser_panel.html as deprecated --- .../templates/wagtailadmin/edit_handlers/chooser_panel.html | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/wagtail/wagtailadmin/templates/wagtailadmin/edit_handlers/chooser_panel.html b/wagtail/wagtailadmin/templates/wagtailadmin/edit_handlers/chooser_panel.html index a3073f037..5413952d1 100644 --- a/wagtail/wagtailadmin/templates/wagtailadmin/edit_handlers/chooser_panel.html +++ b/wagtail/wagtailadmin/templates/wagtailadmin/edit_handlers/chooser_panel.html @@ -1,6 +1,12 @@ {% extends "wagtailadmin/shared/field.html" %} {% load i18n %} {% comment %} + ------ + DEPRECATED - provided for backwards compatibility with custom (third-party) chooser panels + created prior to Wagtail 0.9. New choosers should subclass wagtail.wagtailadmin.widgets.AdminChooser, + with a template that extends wagtailadmin/widgets/chooser.html. + ------ + Either the chosen or unchosen div will be shown, depending on the presence of the 'blank' class on the container. From e3dc4a593602b2e76014910350f7d4a69c228e1a Mon Sep 17 00:00:00 2001 From: Matt Westcott Date: Mon, 9 Feb 2015 19:56:51 +0000 Subject: [PATCH 38/40] cast an empty string value of AdminChooser to None, as needed by required=True validation --- wagtail/wagtailadmin/widgets.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/wagtail/wagtailadmin/widgets.py b/wagtail/wagtailadmin/widgets.py index e53bfb5c1..ae127f2bb 100644 --- a/wagtail/wagtailadmin/widgets.py +++ b/wagtail/wagtailadmin/widgets.py @@ -52,6 +52,14 @@ class AdminChooser(WidgetWithScript, widgets.Input): except model_class.DoesNotExist: return None + def value_from_datadict(self, data, files, name): + # treat the empty string as None + result = super(AdminChooser, self).value_from_datadict(data, files, name) + if result == '': + return None + else: + return result + def __init__(self, **kwargs): # allow choose_one_text / choose_another_text to be overridden per-instance if 'choose_one_text' in kwargs: From 9a3893798e635c270550b7e55af6f5fdc334b60b Mon Sep 17 00:00:00 2001 From: Matt Westcott Date: Mon, 9 Feb 2015 21:25:31 +0000 Subject: [PATCH 39/40] py3 fix --- wagtail/utils/widgets.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wagtail/utils/widgets.py b/wagtail/utils/widgets.py index cc52ba1c9..6c232bb64 100644 --- a/wagtail/utils/widgets.py +++ b/wagtail/utils/widgets.py @@ -14,7 +14,7 @@ class WidgetWithScript(Widget): # so let's make sure it fails early in the process try: id_ = attrs['id'] - except KeyError, TypeError: + except (KeyError, TypeError): raise TypeError("WidgetWithScript cannot be rendered without an 'id' attribute") widget_html = self.render_html(name, value, attrs) From 75c07af32a4a8eae45a9ee02a0e7c28a8958dec7 Mon Sep 17 00:00:00 2001 From: Matt Westcott Date: Tue, 10 Feb 2015 15:06:38 +0000 Subject: [PATCH 40/40] Additional 0.9 deprecation notes --- docs/releases/0.9.rst | 43 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/docs/releases/0.9.rst b/docs/releases/0.9.rst index 981cd60d1..0101e0760 100644 --- a/docs/releases/0.9.rst +++ b/docs/releases/0.9.rst @@ -28,7 +28,7 @@ Minor features * Removed the need to add permission check on admin views (now automated) * Reversing `django.contrib.auth.admin.login` will no longer lead to Wagtails login view (making it easier to have front end views) * Added cache-control headers to all admin views. This allows Varnish/Squid/CDN to run on vanilla settings in front of a Wagtail site - * Added validation to prevent pages being crated with only whitespace characters in their title fields + * Added validation to prevent pages being created with only whitespace characters in their title fields * Page model fields without a FieldPanel are no longer displayed in the form * No longer need to specify the base model on InlinePanel definitions @@ -47,18 +47,51 @@ This release drops support for Django 1.6, Python 2.6/3.2 and Elasticsearch 0.90 If you are upgrading from Elasticsearch 0.90.x, you may also need to update the ``elasticsearch`` pip package to a version greater than ``1.0`` as well. +InlinePanel definitions no longer need to specify the base model +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In previous versions of Wagtail, inline child blocks on a page or snippet were defined using a declaration like:: + + InlinePanel(HomePage, 'carousel_items', label="Carousel items") + +It is no longer necessary to pass the base model as a parameter, so this declaration should be changed to:: + + InlinePanel('carousel_items', label="Carousel items") + +The old format is now deprecated; all existing InlinePanel declarations should be updated to the new format. + Login/Password reset views renamed ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ It was previously possible to reverse the Wagtail login using django.contrib.auth.views.login. -This is no longer possible. Update any references to `wagtailadmin_login`. +This is no longer possible. Update any references to ``wagtailadmin_login``. -Password reset view name has changed from `password_reset` to `wagtailadmin_password_reset`. +Password reset view name has changed from ``password_reset`` to ``wagtailadmin_password_reset``. -You no longer need `LOGIN_URL` and `LOGIN_REDIRECT_URL` to point to Wagtail admin. -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +You no longer need ``LOGIN_URL`` and ``LOGIN_REDIRECT_URL`` to point to Wagtail admin. +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Javascript includes in admin backend have been moved ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ To improve compatibility with third-party form widgets, pages within the Wagtail admin backend now output their Javascript includes in the HTML header, rather than at the end of the page. If your project extends the admin backend (through the ``register_admin_menu_item`` hook, for example) you will need to ensure that all associated Javascript code runs correctly from the new location. In particular, any code that accesses HTML elements will need to be contained in an 'onload' handler (e.g. jQuery's ``$(document).ready()``). + +EditHandler internal API has changed +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +While it is not an official Wagtail API, it has been possible for Wagtail site implementers to define their own ``EditHandler`` subclasses for use in panel definitions, to customise the behaviour of the page / snippet editing forms. If you have made use of this facility, you will need to update your custom EditHandlers, as this mechanism has been refactored (to allow EditHandler classes to keep a persistent reference to their corresponding model). If you have only used Wagtail's built-in panel types (``FieldPanel``, ``InlinePanel``, ``PageChooserPanel`` and so on), you are unaffected by this change. + +Previously, functions like ``FieldPanel`` acted as 'factory' functions, where a call such as ``FieldPanel('title')`` constructed and returned an ``EditHandler`` subclass tailored to work on a 'title' field. These functions now return an object with a ``bind_to_model`` method instead; the EditHandler subclass can be obtained by calling this with the model class as a parameter. As a guide to updating your custom EditHandler code, you may wish to refer to `the relevant change to the Wagtail codebase `_. + +chooser_panel templates are obsolete +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you have added your own custom admin views to the Wagtail admin (e.g. through the ``register_admin_urls`` hook), you may have used one of the following template includes to incorporate a chooser element for pages, documents, images or snippets into your forms: + +- ``wagtailadmin/edit_handlers/chooser_panel.html`` +- ``wagtailadmin/edit_handlers/page_chooser_panel.html`` +- ``wagtaildocs/edit_handlers/document_chooser_panel.html`` +- ``wagtailimages/edit_handlers/image_chooser_panel.html`` +- ``wagtailsnippets/edit_handlers/snippet_chooser_panel.html`` + +All of these templates are now deprecated. Wagtail now provides a set of Django form widgets for this purpose - ``AdminPageChooser``, ``AdminDocumentChooser``, ``AdminImageChooser`` and ``AdminSnippetChooser`` - which can be used in place of the ``HiddenInput`` widget that these form fields were previously using. The field can then be rendered using the regular ``wagtailadmin/shared/field.html`` or ``wagtailadmin/shared/field_as_li.html`` template.