kopia lustrzana https://github.com/wagtail/wagtail
Update type(), not_type(), exact_type() and not_exact_type() to accept multiple model classes as arguments
rodzic
49e18d7ad8
commit
8f38aaae87
docs/reference/pages
wagtail/core
|
@ -207,9 +207,12 @@ Reference
|
|||
|
||||
.. code-block:: python
|
||||
|
||||
# Find all pages that are of type AbstractEmailForm, or a descendant of it
|
||||
# Find all pages that are of type AbstractEmailForm, or one of it's subclasses
|
||||
form_pages = Page.objects.type(AbstractEmailForm)
|
||||
|
||||
# Find all pages that are of type AbstractEmailForm or AbstractEventPage, or one of their subclasses
|
||||
form_and_event_pages = Page.objects.type(AbstractEmailForm, AbstractEventPage)
|
||||
|
||||
.. automethod:: not_type
|
||||
|
||||
.. automethod:: exact_type
|
||||
|
@ -221,14 +224,30 @@ Reference
|
|||
# Find all pages that are of the exact type EventPage
|
||||
event_pages = Page.objects.exact_type(EventPage)
|
||||
|
||||
# Find all page of the exact type EventPage or NewsPage
|
||||
news_and_events_pages = Page.objects.exact_type(EventPage, NewsPage)
|
||||
|
||||
.. note::
|
||||
|
||||
If you are only interested in pages of a single type, it is clearer (and often more efficient) to use
|
||||
the specific model's manager to get a queryset. For example:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
event_pages = EventPage.objects.all()
|
||||
|
||||
.. 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)
|
||||
# First, find all news and event pages
|
||||
news_and_events = Page.objects.type(NewsPage, EventPage)
|
||||
|
||||
# Now exclude pages with an exact type of EventPage or NewsPage,
|
||||
# leaving only instance of more 'specialist' types
|
||||
specialised_news_and_events = news_and_events.not_exact_type(NewsPage, EventPage)
|
||||
|
||||
.. automethod:: unpublish
|
||||
|
||||
|
|
|
@ -180,43 +180,44 @@ class PageQuerySet(SearchableQuerySetMixin, TreeQuerySet):
|
|||
"""
|
||||
return self.exclude(self.page_q(other))
|
||||
|
||||
def type_q(self, klass):
|
||||
content_types = ContentType.objects.get_for_models(*[
|
||||
def type_q(self, *types):
|
||||
all_subclasses = set(
|
||||
model for model in apps.get_models()
|
||||
if issubclass(model, klass)
|
||||
]).values()
|
||||
if issubclass(model, types)
|
||||
)
|
||||
content_types = ContentType.objects.get_for_models(*all_subclasses)
|
||||
return Q(content_type__in=list(content_types.values()))
|
||||
|
||||
return Q(content_type__in=list(content_types))
|
||||
|
||||
def type(self, model):
|
||||
def type(self, *types):
|
||||
"""
|
||||
This filters the QuerySet to only contain pages that are an instance
|
||||
of the specified model (including subclasses).
|
||||
of the specified model(s) (including subclasses).
|
||||
"""
|
||||
return self.filter(self.type_q(model))
|
||||
return self.filter(self.type_q(*types))
|
||||
|
||||
def not_type(self, model):
|
||||
def not_type(self, *types):
|
||||
"""
|
||||
This filters the QuerySet to not contain any pages which are an instance of the specified model.
|
||||
This filters the QuerySet to exclude any pages which are an instance of the specified model(s).
|
||||
"""
|
||||
return self.exclude(self.type_q(model))
|
||||
return self.exclude(self.type_q(*types))
|
||||
|
||||
def exact_type_q(self, klass):
|
||||
return Q(content_type=ContentType.objects.get_for_model(klass))
|
||||
def exact_type_q(self, *types):
|
||||
content_types = ContentType.objects.get_for_models(*types)
|
||||
return Q(content_type__in=list(content_types.values()))
|
||||
|
||||
def exact_type(self, model):
|
||||
def exact_type(self, *types):
|
||||
"""
|
||||
This filters the QuerySet to only contain pages that are an instance of the specified model
|
||||
This filters the QuerySet to only contain pages that are an instance of the specified model(s)
|
||||
(matching the model exactly, not subclasses).
|
||||
"""
|
||||
return self.filter(self.exact_type_q(model))
|
||||
return self.filter(self.exact_type_q(*types))
|
||||
|
||||
def not_exact_type(self, model):
|
||||
def not_exact_type(self, *types):
|
||||
"""
|
||||
This filters the QuerySet to not contain any pages which are an instance of the specified model
|
||||
This filters the QuerySet to exclude any pages which are an instance of the specified model(s)
|
||||
(matching the model exactly, not subclasses).
|
||||
"""
|
||||
return self.exclude(self.exact_type_q(model))
|
||||
return self.exclude(self.exact_type_q(*types))
|
||||
|
||||
def public_q(self):
|
||||
from wagtail.core.models import PageViewRestriction
|
||||
|
|
|
@ -298,24 +298,34 @@ class TestPageQuerySet(TestCase):
|
|||
|
||||
# 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())
|
||||
self.assertIn(event, pages)
|
||||
|
||||
# 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())
|
||||
self.assertIn(event, pages)
|
||||
|
||||
def test_type_includes_subclasses(self):
|
||||
from wagtail.contrib.forms.models import AbstractEmailForm
|
||||
pages = Page.objects.type(AbstractEmailForm)
|
||||
def test_type_with_multiple_models(self):
|
||||
pages = Page.objects.type(EventPage, SimplePage)
|
||||
|
||||
# Check that all objects are instances of AbstractEmailForm
|
||||
# Check that all objects are EventPages or SimplePages
|
||||
for page in pages:
|
||||
self.assertIsInstance(page.specific, AbstractEmailForm)
|
||||
self.assertTrue(
|
||||
isinstance(page.specific, (EventPage, SimplePage))
|
||||
)
|
||||
|
||||
# Check that the contact form page is in the results
|
||||
contact_us = Page.objects.get(url_path='/home/contact-us/')
|
||||
self.assertTrue(pages.filter(id=contact_us.id).exists())
|
||||
# Check that "someone elses event" is in the results
|
||||
event = Page.objects.get(url_path='/home/events/someone-elses-event/')
|
||||
self.assertIn(event, pages)
|
||||
|
||||
# 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.assertIn(event, pages)
|
||||
|
||||
# Check that "About us" (an instance of SimplePage) is in the results
|
||||
about_us = Page.objects.get(url_path='/home/about-us/')
|
||||
self.assertIn(about_us, pages)
|
||||
|
||||
def test_not_type(self):
|
||||
pages = Page.objects.not_type(EventPage)
|
||||
|
@ -324,41 +334,104 @@ class TestPageQuerySet(TestCase):
|
|||
for page in pages:
|
||||
self.assertNotIsInstance(page.specific, EventPage)
|
||||
|
||||
# Check that "About us" is in the results
|
||||
about_us = Page.objects.get(url_path='/home/about-us/')
|
||||
self.assertIn(about_us, pages)
|
||||
|
||||
# Check that the homepage is in the results
|
||||
homepage = Page.objects.get(url_path='/home/')
|
||||
self.assertTrue(pages.filter(id=homepage.id).exists())
|
||||
self.assertIn(homepage, pages)
|
||||
|
||||
def test_not_type_with_multiple_models(self):
|
||||
pages = Page.objects.not_type(EventPage, SimplePage)
|
||||
|
||||
# Check that no objects are EventPages or SimplePages
|
||||
for page in pages:
|
||||
self.assertFalse(
|
||||
isinstance(page.specific, (EventPage, SimplePage))
|
||||
)
|
||||
|
||||
# Check that "About us" is NOT in the results
|
||||
about_us = Page.objects.get(url_path='/home/about-us/')
|
||||
self.assertNotIn(about_us, pages)
|
||||
|
||||
# Check that the homepage IS in the results
|
||||
homepage = Page.objects.get(url_path='/home/')
|
||||
self.assertIn(homepage, pages)
|
||||
|
||||
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)
|
||||
self.assertIs(page.specific_class, 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())
|
||||
self.assertIn(event, pages)
|
||||
|
||||
# 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())
|
||||
single_event = Page.objects.get(url_path='/home/events/saint-patrick/')
|
||||
self.assertNotIn(single_event, pages)
|
||||
|
||||
def test_exact_type_with_multiple_models(self):
|
||||
pages = Page.objects.exact_type(EventPage, Page)
|
||||
|
||||
# Check that all objects are EventPages or Pages (and not a subclass)
|
||||
for page in pages:
|
||||
self.assertIn(page.specific_class, (EventPage, Page))
|
||||
|
||||
# Check that "someone elses event" is in the results
|
||||
event = Page.objects.get(url_path='/home/events/someone-elses-event/')
|
||||
self.assertIn(event, pages)
|
||||
|
||||
# Check that "Saint Patrick" (an instance of SingleEventPage, a subclass of EventPage
|
||||
# and Page) is NOT in the results
|
||||
single_event = Page.objects.get(url_path='/home/events/saint-patrick/')
|
||||
self.assertNotIn(single_event, pages)
|
||||
|
||||
# Check that the homepage (a generic Page only) is in the results
|
||||
homepage = Page.objects.get(url_path='/home/')
|
||||
self.assertIn(homepage, pages)
|
||||
|
||||
# Check that "About us" (an instance of SimplePage, a subclass of Page)
|
||||
# is NOT in the results
|
||||
about_us = Page.objects.get(url_path='/home/about-us/')
|
||||
self.assertNotIn(about_us, pages)
|
||||
|
||||
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)
|
||||
self.assertIsNot(page.specific_class, EventPage)
|
||||
|
||||
# Check that the homepage is in the results
|
||||
homepage = Page.objects.get(url_path='/home/')
|
||||
self.assertTrue(pages.filter(id=homepage.id).exists())
|
||||
self.assertIn(homepage, pages)
|
||||
|
||||
# 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())
|
||||
self.assertIn(event, pages)
|
||||
|
||||
def test_not_exact_type_with_multiple_models(self):
|
||||
pages = Page.objects.not_exact_type(EventPage, Page)
|
||||
|
||||
# Check that no objects are EventPages or generic Pages
|
||||
for page in pages:
|
||||
self.assertNotIn(page.specific_class, (EventPage, Page))
|
||||
|
||||
# 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.assertIn(event, pages)
|
||||
|
||||
# Check that "About us" (an instance of SimplePage, a subclass of Page)
|
||||
# is in the results
|
||||
about_us = Page.objects.get(url_path='/home/about-us/')
|
||||
self.assertIn(about_us, pages)
|
||||
|
||||
def test_public(self):
|
||||
events_index = Page.objects.get(url_path='/home/events/')
|
||||
|
|
Ładowanie…
Reference in New Issue