mirror of
https://github.com/wagtail/wagtail.git
synced 2024-11-29 17:36:49 +01:00
Stop replace_text from replacing multiple times on MTI subclasses.
Iterating over get_page_models means that these will be visited once per superclass. To avoid this, we filter the page list to those exactly matching the page class. This is done via a new `exact_type` method on `PageQuerySet`.
This commit is contained in:
parent
1bb74ee4d0
commit
b1c75644f6
@ -202,6 +202,24 @@ Reference
|
||||
|
||||
.. automethod:: not_type
|
||||
|
||||
.. automethod:: exact_type
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# Find all pages that are of the exact type EventPage
|
||||
event_pages = Page.objects.exact_type(EventPage)
|
||||
|
||||
.. automethod:: not_exact_type
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# Find all pages that are not of the exact type EventPage (but may be a subclass)
|
||||
non_event_pages = Page.objects.not_exact_type(EventPage)
|
||||
|
||||
.. automethod:: unpublish
|
||||
|
||||
Example:
|
||||
|
@ -32,7 +32,10 @@ class Command(BaseCommand):
|
||||
|
||||
child_relation_names = [rel.get_accessor_name() for rel in get_all_child_relations(page_class)]
|
||||
|
||||
for page in page_class.objects.all():
|
||||
# Find all pages of this exact type; exclude subclasses, as they will
|
||||
# appear in the get_page_models() list in their own right, and this
|
||||
# ensures that replacement happens only once
|
||||
for page in page_class.objects.exact_type(page_class):
|
||||
replace_in_model(page, from_text, to_text)
|
||||
for child_rel in child_relation_names:
|
||||
for child in getattr(page, child_rel).all():
|
||||
|
@ -191,6 +191,23 @@ class PageQuerySet(SearchableQuerySetMixin, TreeQuerySet):
|
||||
"""
|
||||
return self.exclude(self.type_q(model))
|
||||
|
||||
def exact_type_q(self, klass):
|
||||
return Q(content_type=ContentType.objects.get_for_model(klass))
|
||||
|
||||
def exact_type(self, model):
|
||||
"""
|
||||
This filters the QuerySet to only contain pages that are an instance of the specified model
|
||||
(matching the model exactly, not subclasses).
|
||||
"""
|
||||
return self.filter(self.exact_type_q(model))
|
||||
|
||||
def not_exact_type(self, model):
|
||||
"""
|
||||
This filters the QuerySet to not contain any pages which are an instance of the specified model
|
||||
(matching the model exactly, not subclasses).
|
||||
"""
|
||||
return self.exclude(self.exact_type_q(model))
|
||||
|
||||
def public_q(self):
|
||||
from wagtail.wagtailcore.models import PageViewRestriction
|
||||
|
||||
|
@ -294,6 +294,11 @@ class TestPageQuerySet(TestCase):
|
||||
event = Page.objects.get(url_path='/home/events/someone-elses-event/')
|
||||
self.assertTrue(pages.filter(id=event.id).exists())
|
||||
|
||||
# Check that "Saint Patrick" (an instance of SingleEventPage, a subclass of EventPage)
|
||||
# is in the results
|
||||
event = Page.objects.get(url_path='/home/events/saint-patrick/')
|
||||
self.assertTrue(pages.filter(id=event.id).exists())
|
||||
|
||||
def test_type_includes_subclasses(self):
|
||||
from wagtail.wagtailforms.models import AbstractEmailForm
|
||||
pages = Page.objects.type(AbstractEmailForm)
|
||||
@ -317,6 +322,38 @@ class TestPageQuerySet(TestCase):
|
||||
homepage = Page.objects.get(url_path='/home/')
|
||||
self.assertTrue(pages.filter(id=homepage.id).exists())
|
||||
|
||||
def test_exact_type(self):
|
||||
pages = Page.objects.exact_type(EventPage)
|
||||
|
||||
# Check that all objects are EventPages (and not a subclass)
|
||||
for page in pages:
|
||||
self.assertEqual(type(page.specific), EventPage)
|
||||
|
||||
# Check that "someone elses event" is in the results
|
||||
event = Page.objects.get(url_path='/home/events/someone-elses-event/')
|
||||
self.assertTrue(pages.filter(id=event.id).exists())
|
||||
|
||||
# Check that "Saint Patrick" (an instance of SingleEventPage, a subclass of EventPage)
|
||||
# is NOT in the results
|
||||
event = Page.objects.get(url_path='/home/events/saint-patrick/')
|
||||
self.assertFalse(pages.filter(id=event.id).exists())
|
||||
|
||||
def test_not_exact_type(self):
|
||||
pages = Page.objects.not_exact_type(EventPage)
|
||||
|
||||
# Check that no objects are EventPages
|
||||
for page in pages:
|
||||
self.assertNotEqual(type(page.specific), EventPage)
|
||||
|
||||
# Check that the homepage is in the results
|
||||
homepage = Page.objects.get(url_path='/home/')
|
||||
self.assertTrue(pages.filter(id=homepage.id).exists())
|
||||
|
||||
# Check that "Saint Patrick" (an instance of SingleEventPage, a subclass of EventPage)
|
||||
# is in the results
|
||||
event = Page.objects.get(url_path='/home/events/saint-patrick/')
|
||||
self.assertTrue(pages.filter(id=event.id).exists())
|
||||
|
||||
def test_public(self):
|
||||
events_index = Page.objects.get(url_path='/home/events/')
|
||||
event = Page.objects.get(url_path='/home/events/christmas/')
|
||||
|
Loading…
Reference in New Issue
Block a user