Added an option to the page model to be able to define the amount of subpages underneath a specific parent page

pull/5155/head
Wesley van Lee 2019-03-15 12:32:54 +01:00 zatwierdzone przez Matt Westcott
rodzic 339b6752af
commit c831d434ab
7 zmienionych plików z 78 dodań i 2 usunięć

Wyświetl plik

@ -20,6 +20,7 @@ Changelog
* Added instructions on how to generate urls for `ModelAdmin` to documentation (LB (Ben Johnston), Andy Babic)
* Added option to specify a fallback URL on `{% pageurl %}` (Arthur Holzner)
* Add support for more rich text formats, disabled by default: `blockquote`, `superscript`, `subscript`, `strikethrough`, `code` (Md Arifin Ibne Matin)
* Added `max_count_per_parent` option on page models to limit the number of pages of a given type that can be created under one parent page (Wesley van Lee)
* Fix: Set `SERVER_PORT` to 443 in `Page.dummy_request()` for HTTPS sites (Sergey Fedoseev)
* Fix: Include port number in `Host` header of `Page.dummy_request()` (Sergey Fedoseev)
* Fix: Validation error messages in `InlinePanel` no longer count towards `max_num` when disabling the 'add' button (Todd Dembrey, Thibaud Colas)

Wyświetl plik

@ -203,6 +203,10 @@ In addition to the model fields provided, ``Page`` has many properties and metho
Controls the maximum number of pages of this type that can be created through the Wagtail administration interface. This is useful when needing "allow at most 3 of these pages to exist", or for singleton pages.
.. attribute:: max_count_per_parent
Controls the maximum number of pages of this type that can be created under any one parent page.
.. attribute:: exclude_fields_in_copy
An array of field names that will not be included when a Page is copied.

Wyświetl plik

@ -30,6 +30,7 @@ Other features
* Added instructions on how to generate urls for ``ModelAdmin`` to documentation (LB (Ben Johnston), Andy Babic)
* Added option to specify a fallback URL on ``{% pageurl %}`` (Arthur Holzner)
* Add support for more rich text formats, disabled by default: ``blockquote``, ``superscript``, ``subscript``, ``strikethrough``, ``code`` (Md Arifin Ibne Matin)
* Added ``max_count_per_parent`` option on page models to limit the number of pages of a given type that can be created under one parent page (Wesley van Lee)
Bug fixes

Wyświetl plik

@ -343,6 +343,9 @@ class Page(AbstractPage, index.Indexed, ClusterableModel, metaclass=PageBase):
# Define the maximum number of instances this page type can have. Default to unlimited.
max_count = None
# Define the maximum number of instances this page can have under a specific parent. Default to unlimited.
max_count_per_parent = None
# An array of additional field names that will not be included when a Page is copied.
exclude_fields_in_copy = []
@ -980,6 +983,9 @@ class Page(AbstractPage, index.Indexed, ClusterableModel, metaclass=PageBase):
if cls.max_count is not None:
can_create = can_create and cls.objects.count() < cls.max_count
if cls.max_count_per_parent is not None:
can_create = can_create and parent.get_children().type(cls).count() < cls.max_count_per_parent
return can_create
def can_move_to(self, parent):

Wyświetl plik

@ -17,8 +17,8 @@ from wagtail.tests.testapp.models import (
AbstractPage, Advert, AlwaysShowInMenusPage, BlogCategory, BlogCategoryBlogPage, BusinessChild,
BusinessIndex, BusinessNowherePage, BusinessSubIndex, CustomManager, CustomManagerPage,
CustomPageQuerySet, EventCategory, EventIndex, EventPage, GenericSnippetPage, ManyToManyBlogPage,
MTIBasePage, MTIChildPage, MyCustomPage, OneToOnePage, PageWithExcludedCopyField, SimplePage,
SingleEventPage, SingletonPage, StandardIndex, TaggedPage)
MTIBasePage, MTIChildPage, MyCustomPage, OneToOnePage, PageWithExcludedCopyField, SimpleChildPage,
SimplePage, SimpleParentPage, SingleEventPage, SingletonPage, StandardIndex, TaggedPage)
from wagtail.tests.utils import WagtailTestUtils
@ -1167,6 +1167,23 @@ class TestSubpageTypeBusinessRules(TestCase, WagtailTestUtils):
self.assertFalse(BusinessChild.can_create_at(SimplePage()))
self.assertFalse(BusinessSubIndex.can_create_at(SimplePage()))
def test_can_create_at_with_max_count_per_parent_limited_to_one(self):
root_page = Page.objects.get(url_path='/home/')
# Create 2 parent pages for our limited page model
parent1 = root_page.add_child(instance=SimpleParentPage(title='simple parent', slug='simple-parent'))
parent2 = root_page.add_child(instance=SimpleParentPage(title='simple parent', slug='simple-parent-2'))
# Add a child page to one of the pages (assert just to be sure)
self.assertTrue(SimpleChildPage.can_create_at(parent1))
parent1.add_child(instance=SimpleChildPage(title='simple child', slug='simple-child'))
# We already have a `SimpleChildPage` as a child of `parent1`, and since it is limited
# to have only 1 child page, we cannot create anoter one. However, we should still be able
# to create an instance for this page at a different location (as child of `parent2`)
self.assertFalse(SimpleChildPage.can_create_at(parent1))
self.assertTrue(SimpleChildPage.can_create_at(parent2))
def test_can_move_to(self):
self.assertTrue(SimplePage().can_move_to(SimplePage()))

Wyświetl plik

@ -0,0 +1,35 @@
# Generated by Django 2.1.7 on 2019-03-15 10:39
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('wagtailcore', '0041_group_collection_permissions_verbose_name_plural'),
('tests', '0041_secretpage'),
]
operations = [
migrations.CreateModel(
name='SimpleChildPage',
fields=[
('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.Page')),
],
options={
'abstract': False,
},
bases=('wagtailcore.page',),
),
migrations.CreateModel(
name='SimpleParentPage',
fields=[
('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.Page')),
],
options={
'abstract': False,
},
bases=('wagtailcore.page',),
),
]

Wyświetl plik

@ -1327,3 +1327,15 @@ class SecretPage(PerUserPageMixin, Page):
superuser_content_panels = basic_content_panels + [
FieldPanel('secret_data'),
]
class SimpleParentPage(Page):
# `BusinessIndex` has been added to bring it in line with other tests
subpage_types = ['tests.SimpleChildPage', BusinessIndex]
class SimpleChildPage(Page):
# `Page` has been added to bring it in line with other tests
parent_page_types = ['tests.SimpleParentPage', Page]
max_count_per_parent = 1