diff --git a/wagtail/tests/models.py b/wagtail/tests/models.py index c419de7c7..086c2af15 100644 --- a/wagtail/tests/models.py +++ b/wagtail/tests/models.py @@ -20,6 +20,7 @@ from wagtail.wagtailsnippets.models import register_snippet from wagtail.wagtailsnippets.edit_handlers import SnippetChooserPanel from wagtail.wagtailsearch import index from wagtail.contrib.wagtailroutablepage.models import RoutablePage +from wagtail.wagtailimages.models import AbstractImage, Image EVENT_AUDIENCE_CHOICES = ( @@ -522,3 +523,17 @@ register_snippet(RegisterFunction) @register_snippet class RegisterDecorator(models.Model): pass + + +class CustomImageWithoutAdminFormFields(AbstractImage): + caption = models.CharField(max_length=255) + not_editable_field = models.CharField(max_length=255) + + +class CustomImageWithAdminFormFields(AbstractImage): + caption = models.CharField(max_length=255) + not_editable_field = models.CharField(max_length=255) + + admin_form_fields = Image.admin_form_fields + ( + 'caption', + ) diff --git a/wagtail/wagtailimages/forms.py b/wagtail/wagtailimages/forms.py index faf1dd703..e3db916c8 100644 --- a/wagtail/wagtailimages/forms.py +++ b/wagtail/wagtailimages/forms.py @@ -1,7 +1,10 @@ +import warnings + from django import forms from django.forms.models import modelform_factory from django.utils.translation import ugettext as _ +from wagtail.utils.deprecation import RemovedInWagtail11Warning from wagtail.wagtailimages.formats import get_image_formats from wagtail.wagtailimages.fields import WagtailImageField @@ -17,9 +20,20 @@ def formfield_for_dbfield(db_field, **kwargs): def get_image_form(model): + if hasattr(model, 'admin_form_fields'): + fields = model.admin_form_fields + else: + fields = '__all__' + + warnings.warn( + "Custom image models without an 'admin_form_fields' attribute are now deprecated. " + "Add admin_form_fields = (tuple of field names) to {classname}".format( + classname=model.__name__ + ), RemovedInWagtail11Warning, stacklevel=2) + return modelform_factory( model, - fields=model.admin_form_fields, + fields=fields, formfield_callback=formfield_for_dbfield, # set the 'file' widget to a FileInput rather than the default ClearableFileInput # so that when editing, we don't get the 'currently: ...' banner which is diff --git a/wagtail/wagtailimages/models.py b/wagtail/wagtailimages/models.py index 9fd84f2e4..18f1e3aef 100644 --- a/wagtail/wagtailimages/models.py +++ b/wagtail/wagtailimages/models.py @@ -67,16 +67,6 @@ class AbstractImage(models.Model, TagSearchable): focal_point_width = models.PositiveIntegerField(null=True, blank=True) focal_point_height = models.PositiveIntegerField(null=True, blank=True) - admin_form_fields = ( - 'title', - 'file', - 'tags', - 'focal_point_x', - 'focal_point_y', - 'focal_point_width', - 'focal_point_height', - ) - def get_usage(self): return get_object_usage(self) @@ -235,7 +225,15 @@ class AbstractImage(models.Model, TagSearchable): class Image(AbstractImage): - pass + admin_form_fields = ( + 'title', + 'file', + 'tags', + 'focal_point_x', + 'focal_point_y', + 'focal_point_width', + 'focal_point_height', + ) # Do smartcropping calculations when user saves an image without a focal point diff --git a/wagtail/wagtailimages/tests/tests.py b/wagtail/wagtailimages/tests/tests.py index f5cde5bd0..cda29df3c 100644 --- a/wagtail/wagtailimages/tests/tests.py +++ b/wagtail/wagtailimages/tests/tests.py @@ -1,4 +1,5 @@ import datetime +import warnings from contextlib import contextmanager from mock import MagicMock @@ -11,6 +12,9 @@ from django.db import models from taggit.forms import TagField, TagWidget +from wagtail.utils.deprecation import RemovedInWagtail11Warning +from wagtail.tests.models import CustomImageWithAdminFormFields, CustomImageWithoutAdminFormFields +from wagtail.tests.utils import WagtailTestUtils from wagtail.wagtailimages.utils import generate_signature, verify_signature from wagtail.wagtailimages.rect import Rect from wagtail.wagtailimages.formats import Format, get_image_format, register_image_format @@ -250,7 +254,7 @@ class TestRect(TestCase): self.assertEqual(rect.get_key(), '150-200-100x100') -class TestGetImageForm(TestCase): +class TestGetImageForm(TestCase, WagtailTestUtils): def test_fields(self): form = get_image_form(Image) @@ -264,24 +268,41 @@ class TestGetImageForm(TestCase): 'focal_point_height', ]) - @contextmanager - def patch_admin_form_fields(self, image_model, admin_form_fields): - old_admin_form_fields = image_model.admin_form_fields - image_model.admin_form_fields = admin_form_fields - yield - image_model.admin_form_fields = old_admin_form_fields - def test_admin_form_fields_attribute(self): - # Remove focal point fields - admin_form_fields = Image.admin_form_fields[:-4] - - with self.patch_admin_form_fields(Image, admin_form_fields): - form = get_image_form(Image) + form = get_image_form(CustomImageWithAdminFormFields) self.assertEqual(list(form.base_fields.keys()), [ 'title', 'file', 'tags', + 'focal_point_x', + 'focal_point_y', + 'focal_point_width', + 'focal_point_height', + 'caption', + ]) + + def test_custom_image_model_without_admin_form_fields_raises_warning(self): + self.reset_warning_registry() + with warnings.catch_warnings(record=True) as w: + form = get_image_form(CustomImageWithoutAdminFormFields) + + # Check that a RemovedInWagtail11Warning has been triggered + self.assertEqual(len(w), 1) + self.assertTrue(issubclass(w[-1].category, RemovedInWagtail11Warning)) + self.assertTrue("Add admin_form_fields = (tuple of field names) to CustomImageWithoutAdminFormFields" in str(w[-1].message)) + + # All fields, including the not editable one should be on the form + self.assertEqual(list(form.base_fields.keys()), [ + 'title', + 'file', + 'focal_point_x', + 'focal_point_y', + 'focal_point_width', + 'focal_point_height', + 'caption', + 'not_editable_field', + 'tags', ]) def test_file_field(self):