From 6821c763ea6d17f134a1fb2c138f57d97cf65ca7 Mon Sep 17 00:00:00 2001 From: Thejaswi Puthraya Date: Sat, 18 Jun 2016 22:54:55 +0530 Subject: [PATCH] Refs #2717. Custom forms for modeladmin. --- CHANGELOG.txt | 1 + CONTRIBUTORS.rst | 1 + docs/releases/1.8.rst | 1 + .../tests/test_simple_modeladmin.py | 15 +++++++++++- wagtail/tests/modeladmintest/forms.py | 9 ++++++++ .../migrations/0003_publisher.py | 23 +++++++++++++++++++ wagtail/tests/modeladmintest/models.py | 9 ++++++++ wagtail/tests/modeladmintest/wagtail_hooks.py | 15 +++++++++++- wagtail/wagtailadmin/edit_handlers.py | 14 +++++++---- 9 files changed, 82 insertions(+), 6 deletions(-) create mode 100644 wagtail/tests/modeladmintest/forms.py create mode 100644 wagtail/tests/modeladmintest/migrations/0003_publisher.py diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 96015bcca8..ed59537c16 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -13,6 +13,7 @@ Changelog * Added `first_common_ancestor` method to `PageQuerySet` (Tim Heap) * Page chooser now opens at the deepest ancestor page that covers all the pages of the required page type (Tim Heap) * `PageChooserBlock` now accepts a `target_model` option to specify the required page type (Tim Heap) + * Modeladmin forms now respect `fields` / `exclude` options passed on custom model forms (Thejaswi Puthraya) * Fix: `AbstractForm` now respects custom `get_template` methods on the page model (Gagaro) * Fix: Use specific page model for the parent page in the explore index (Gagaro) * Fix: Remove responsive styles in embed when there is no ratio available (Gagaro) diff --git a/CONTRIBUTORS.rst b/CONTRIBUTORS.rst index 1adffa6dfd..1cd3f72ecc 100644 --- a/CONTRIBUTORS.rst +++ b/CONTRIBUTORS.rst @@ -181,6 +181,7 @@ Contributors * Luca Perico * Gary Krige * Hammy Goonan +* Thejaswi Puthraya Translators =========== diff --git a/docs/releases/1.8.rst b/docs/releases/1.8.rst index 1dea29f049..62a47406db 100644 --- a/docs/releases/1.8.rst +++ b/docs/releases/1.8.rst @@ -39,6 +39,7 @@ Minor features * Added ``first_common_ancestor`` method to ``PageQuerySet`` (Tim Heap) * Page chooser now opens at the deepest ancestor page that covers all the pages of the required page type (Tim Heap) * ``PageChooserBlock`` now accepts a ``target_model`` option to specify the required page type (Tim Heap) + * Modeladmin forms now respect ``fields`` / ``exclude`` options passed on custom model forms (Thejaswi Puthraya) Bug fixes diff --git a/wagtail/contrib/modeladmin/tests/test_simple_modeladmin.py b/wagtail/contrib/modeladmin/tests/test_simple_modeladmin.py index 00da8db20d..581dc2994e 100644 --- a/wagtail/contrib/modeladmin/tests/test_simple_modeladmin.py +++ b/wagtail/contrib/modeladmin/tests/test_simple_modeladmin.py @@ -4,7 +4,7 @@ from django.contrib.auth import get_user_model from django.contrib.auth.models import Group from django.test import TestCase -from wagtail.tests.modeladmintest.models import Author, Book +from wagtail.tests.modeladmintest.models import Author, Book, Publisher from wagtail.tests.utils import WagtailTestUtils @@ -116,6 +116,19 @@ class TestCreateView(TestCase, WagtailTestUtils): # Check that the book was created self.assertEqual(Book.objects.filter(title="George's Marvellous Medicine").count(), 1) + response = self.client.get('/admin/modeladmintest/publisher/create/') + self.assertIn('name', response.content.decode('UTF-8')) + self.assertNotIn('headquartered_in', response.content.decode('UTF-8')) + self.assertEqual( + [ii for ii in response.context['form'].fields], + ['name'] + ) + self.client.post('/admin/modeladmintest/publisher/create/', { + 'name': 'Sharper Collins' + }) + publisher = Publisher.objects.get(name='Sharper Collins') + self.assertEqual(publisher.headquartered_in, None) + def test_post_invalid(self): initial_book_count = Book.objects.count() diff --git a/wagtail/tests/modeladmintest/forms.py b/wagtail/tests/modeladmintest/forms.py new file mode 100644 index 0000000000..e1a1310d82 --- /dev/null +++ b/wagtail/tests/modeladmintest/forms.py @@ -0,0 +1,9 @@ +from django import forms + +from .models import Publisher + + +class PublisherModelAdminForm(forms.ModelForm): + class Meta: + model = Publisher + fields = ["name"] diff --git a/wagtail/tests/modeladmintest/migrations/0003_publisher.py b/wagtail/tests/modeladmintest/migrations/0003_publisher.py new file mode 100644 index 0000000000..fdb10f2a04 --- /dev/null +++ b/wagtail/tests/modeladmintest/migrations/0003_publisher.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-06-07 11:22 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('modeladmintest', '0002_token'), + ] + + operations = [ + migrations.CreateModel( + name='Publisher', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=50)), + ('headquartered_in', models.CharField(max_length=50, null=True, blank=True)), + ], + ), + ] diff --git a/wagtail/tests/modeladmintest/models.py b/wagtail/tests/modeladmintest/models.py index 5daef59c45..38c4126a60 100644 --- a/wagtail/tests/modeladmintest/models.py +++ b/wagtail/tests/modeladmintest/models.py @@ -30,3 +30,12 @@ class Token(models.Model): def __str__(self): return self.key + + +@python_2_unicode_compatible +class Publisher(models.Model): + name = models.CharField(max_length=50) + headquartered_in = models.CharField(max_length=50, null=True, blank=True) + + def __str__(self): + return self.name diff --git a/wagtail/tests/modeladmintest/wagtail_hooks.py b/wagtail/tests/modeladmintest/wagtail_hooks.py index ff40ae1fbf..a57f648cd9 100644 --- a/wagtail/tests/modeladmintest/wagtail_hooks.py +++ b/wagtail/tests/modeladmintest/wagtail_hooks.py @@ -1,9 +1,11 @@ from __future__ import absolute_import, unicode_literals from wagtail.contrib.modeladmin.options import ModelAdmin, ModelAdminGroup, modeladmin_register +from wagtail.contrib.modeladmin.views import CreateView from wagtail.tests.testapp.models import BusinessChild, EventPage, SingleEventPage -from .models import Author, Book, Token +from .models import Author, Book, Token, Publisher +from .forms import PublisherModelAdminForm class AuthorModelAdmin(ModelAdmin): @@ -38,6 +40,16 @@ class TokenModelAdmin(ModelAdmin): list_display = ('key',) +class PublisherCreateView(CreateView): + def get_form_class(self): + return PublisherModelAdminForm + + +class PublisherModelAdmin(ModelAdmin): + model = Publisher + create_view_class = PublisherCreateView + + class EventPageAdmin(ModelAdmin): model = EventPage list_display = ('title', 'date_from', 'audience') @@ -66,5 +78,6 @@ class BusinessChildAdmin(ModelAdmin): modeladmin_register(AuthorModelAdmin) modeladmin_register(BookModelAdmin) modeladmin_register(TokenModelAdmin) +modeladmin_register(PublisherModelAdmin) modeladmin_register(EventsAdminGroup) modeladmin_register(BusinessChildAdmin) diff --git a/wagtail/wagtailadmin/edit_handlers.py b/wagtail/wagtailadmin/edit_handlers.py index 2aae1e23f0..b028f436d1 100644 --- a/wagtail/wagtailadmin/edit_handlers.py +++ b/wagtail/wagtailadmin/edit_handlers.py @@ -249,10 +249,16 @@ class BaseCompositeEditHandler(EditHandler): def __init__(self, instance=None, form=None): super(BaseCompositeEditHandler, self).__init__(instance=instance, form=form) - self.children = [ - handler_class(instance=self.instance, form=self.form) - for handler_class in self.__class__.children - ] + self.children = [] + for child in self.__class__.children: + if not getattr(child, "children", None) and getattr(child, "field_name", None): + if self.form._meta.exclude: + if child.field_name in self.form._meta.exclude: + continue + if self.form._meta.fields: + if child.field_name not in self.form._meta.fields: + continue + self.children.append(child(instance=self.instance, form=self.form)) def render(self): return mark_safe(render_to_string(self.template, {