From 682232ca5bfc524ccb249da12fa21be6ed6c94c2 Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Mon, 30 Mar 2015 12:39:23 +0100 Subject: [PATCH 01/27] Moved test app into subdirectory - Gives a nice separation between test app and test configuration - Allows us to cleanly add separate test apps --- wagtail/contrib/wagtailroutablepage/tests.py | 2 +- wagtail/contrib/wagtailsitemaps/tests.py | 2 +- wagtail/tests/settings.py | 2 +- wagtail/tests/testapp/__init__.py | 1 + wagtail/tests/testapp/apps.py | 7 +++++++ wagtail/tests/{ => testapp}/fixtures/test.json | 0 .../{ => testapp}/migrations/0001_initial.py | 0 .../migrations/0002_auto_20140827_0908.py | 0 .../migrations/0003_auto_20140905_0634.py | 0 .../migrations/0004_auto_20141008_0420.py | 0 .../migrations/0005_auto_20141008_0122.py | 0 .../migrations/0005_auto_20141113_0642.py | 0 .../{ => testapp}/migrations/0006_merge.py | 0 .../migrations/0007_auto_20141118_0925.py | 0 .../migrations/0008_registerdecorator.py | 0 .../migrations/0009_eventpagechoosermodel.py | 0 ...fields_customimagewithoutadminformfields.py | 0 .../tests/{ => testapp}/migrations/__init__.py | 0 wagtail/tests/{ => testapp}/models.py | 0 .../templates/tests/event_index.html | 0 .../templates/tests/event_page.html | 0 .../tests/event_page_password_required.html | 0 .../templates/tests/form_page.html | 0 .../templates/tests/form_page_landing.html | 0 .../tests/includes/event_listing.html | 0 .../templates/tests/simple_page.html | 0 wagtail/tests/{ => testapp}/wagtail_hooks.py | 0 .../wagtailadmin/tests/test_edit_handlers.py | 2 +- .../wagtailadmin/tests/test_page_chooser.py | 2 +- wagtail/wagtailadmin/tests/test_pages_views.py | 2 +- wagtail/wagtailadmin/tests/test_privacy.py | 2 +- .../tests/test_management_commands.py | 2 +- wagtail/wagtailcore/tests/test_page_model.py | 2 +- .../wagtailcore/tests/test_page_permissions.py | 2 +- .../wagtailcore/tests/test_page_queryset.py | 2 +- wagtail/wagtailcore/tests/test_rich_text.py | 2 +- wagtail/wagtailcore/tests/tests.py | 2 +- wagtail/wagtaildocs/tests.py | 8 ++++---- wagtail/wagtailforms/tests.py | 2 +- wagtail/wagtailimages/tests/test_models.py | 6 +++--- wagtail/wagtailimages/tests/test_rich_text.py | 2 -- wagtail/wagtailimages/tests/tests.py | 2 +- wagtail/wagtailsearch/tests/test_backends.py | 2 +- .../tests/test_elasticsearch_backend.py | 2 +- wagtail/wagtailsearch/tests/test_frontend.py | 2 +- .../wagtailsearch/tests/test_indexed_class.py | 2 +- .../tests/test_signal_handlers.py | 2 +- wagtail/wagtailsnippets/tests.py | 18 +++++++++--------- 48 files changed, 44 insertions(+), 38 deletions(-) create mode 100644 wagtail/tests/testapp/__init__.py create mode 100644 wagtail/tests/testapp/apps.py rename wagtail/tests/{ => testapp}/fixtures/test.json (100%) rename wagtail/tests/{ => testapp}/migrations/0001_initial.py (100%) rename wagtail/tests/{ => testapp}/migrations/0002_auto_20140827_0908.py (100%) rename wagtail/tests/{ => testapp}/migrations/0003_auto_20140905_0634.py (100%) rename wagtail/tests/{ => testapp}/migrations/0004_auto_20141008_0420.py (100%) rename wagtail/tests/{ => testapp}/migrations/0005_auto_20141008_0122.py (100%) rename wagtail/tests/{ => testapp}/migrations/0005_auto_20141113_0642.py (100%) rename wagtail/tests/{ => testapp}/migrations/0006_merge.py (100%) rename wagtail/tests/{ => testapp}/migrations/0007_auto_20141118_0925.py (100%) rename wagtail/tests/{ => testapp}/migrations/0008_registerdecorator.py (100%) rename wagtail/tests/{ => testapp}/migrations/0009_eventpagechoosermodel.py (100%) rename wagtail/tests/{ => testapp}/migrations/0010_customimagewithadminformfields_customimagewithoutadminformfields.py (100%) rename wagtail/tests/{ => testapp}/migrations/__init__.py (100%) rename wagtail/tests/{ => testapp}/models.py (100%) rename wagtail/tests/{ => testapp}/templates/tests/event_index.html (100%) rename wagtail/tests/{ => testapp}/templates/tests/event_page.html (100%) rename wagtail/tests/{ => testapp}/templates/tests/event_page_password_required.html (100%) rename wagtail/tests/{ => testapp}/templates/tests/form_page.html (100%) rename wagtail/tests/{ => testapp}/templates/tests/form_page_landing.html (100%) rename wagtail/tests/{ => testapp}/templates/tests/includes/event_listing.html (100%) rename wagtail/tests/{ => testapp}/templates/tests/simple_page.html (100%) rename wagtail/tests/{ => testapp}/wagtail_hooks.py (100%) diff --git a/wagtail/contrib/wagtailroutablepage/tests.py b/wagtail/contrib/wagtailroutablepage/tests.py index 1aa8f53d1..2e24cb3fe 100644 --- a/wagtail/contrib/wagtailroutablepage/tests.py +++ b/wagtail/contrib/wagtailroutablepage/tests.py @@ -1,7 +1,7 @@ from django.test import TestCase, RequestFactory from wagtail.wagtailcore.models import Page, Site -from wagtail.tests.models import RoutablePageTest, routable_page_external_view +from wagtail.tests.testapp.models import RoutablePageTest, routable_page_external_view from wagtail.contrib.wagtailroutablepage.templatetags.wagtailroutablepage_tags import routablepageurl diff --git a/wagtail/contrib/wagtailsitemaps/tests.py b/wagtail/contrib/wagtailsitemaps/tests.py index a2d0498d7..5fba8f57e 100644 --- a/wagtail/contrib/wagtailsitemaps/tests.py +++ b/wagtail/contrib/wagtailsitemaps/tests.py @@ -2,7 +2,7 @@ from django.test import TestCase from django.core.cache import cache from wagtail.wagtailcore.models import Page, PageViewRestriction, Site -from wagtail.tests.models import SimplePage, EventIndex +from wagtail.tests.testapp.models import SimplePage, EventIndex from .sitemap_generator import Sitemap diff --git a/wagtail/tests/settings.py b/wagtail/tests/settings.py index 3366af818..f198e840d 100644 --- a/wagtail/tests/settings.py +++ b/wagtail/tests/settings.py @@ -76,7 +76,7 @@ INSTALLED_APPS = ( 'wagtail.contrib.wagtailsitemaps', 'wagtail.contrib.wagtailroutablepage', 'wagtail.contrib.wagtailfrontendcache', - 'wagtail.tests', + 'wagtail.tests.testapp', # Install wagtailredirects with its appconfig # Theres nothing special about wagtailredirects, we just need to have one diff --git a/wagtail/tests/testapp/__init__.py b/wagtail/tests/testapp/__init__.py new file mode 100644 index 000000000..accd0aff7 --- /dev/null +++ b/wagtail/tests/testapp/__init__.py @@ -0,0 +1 @@ +default_app_config = 'wagtail.tests.testapp.apps.WagtailTestsAppConfig' diff --git a/wagtail/tests/testapp/apps.py b/wagtail/tests/testapp/apps.py new file mode 100644 index 000000000..8dedd7f25 --- /dev/null +++ b/wagtail/tests/testapp/apps.py @@ -0,0 +1,7 @@ +from django.apps import AppConfig + + +class WagtailTestsAppConfig(AppConfig): + name = 'wagtail.tests.testapp' + label = 'tests' + verbose_name = "Wagtail tests" diff --git a/wagtail/tests/fixtures/test.json b/wagtail/tests/testapp/fixtures/test.json similarity index 100% rename from wagtail/tests/fixtures/test.json rename to wagtail/tests/testapp/fixtures/test.json diff --git a/wagtail/tests/migrations/0001_initial.py b/wagtail/tests/testapp/migrations/0001_initial.py similarity index 100% rename from wagtail/tests/migrations/0001_initial.py rename to wagtail/tests/testapp/migrations/0001_initial.py diff --git a/wagtail/tests/migrations/0002_auto_20140827_0908.py b/wagtail/tests/testapp/migrations/0002_auto_20140827_0908.py similarity index 100% rename from wagtail/tests/migrations/0002_auto_20140827_0908.py rename to wagtail/tests/testapp/migrations/0002_auto_20140827_0908.py diff --git a/wagtail/tests/migrations/0003_auto_20140905_0634.py b/wagtail/tests/testapp/migrations/0003_auto_20140905_0634.py similarity index 100% rename from wagtail/tests/migrations/0003_auto_20140905_0634.py rename to wagtail/tests/testapp/migrations/0003_auto_20140905_0634.py diff --git a/wagtail/tests/migrations/0004_auto_20141008_0420.py b/wagtail/tests/testapp/migrations/0004_auto_20141008_0420.py similarity index 100% rename from wagtail/tests/migrations/0004_auto_20141008_0420.py rename to wagtail/tests/testapp/migrations/0004_auto_20141008_0420.py diff --git a/wagtail/tests/migrations/0005_auto_20141008_0122.py b/wagtail/tests/testapp/migrations/0005_auto_20141008_0122.py similarity index 100% rename from wagtail/tests/migrations/0005_auto_20141008_0122.py rename to wagtail/tests/testapp/migrations/0005_auto_20141008_0122.py diff --git a/wagtail/tests/migrations/0005_auto_20141113_0642.py b/wagtail/tests/testapp/migrations/0005_auto_20141113_0642.py similarity index 100% rename from wagtail/tests/migrations/0005_auto_20141113_0642.py rename to wagtail/tests/testapp/migrations/0005_auto_20141113_0642.py diff --git a/wagtail/tests/migrations/0006_merge.py b/wagtail/tests/testapp/migrations/0006_merge.py similarity index 100% rename from wagtail/tests/migrations/0006_merge.py rename to wagtail/tests/testapp/migrations/0006_merge.py diff --git a/wagtail/tests/migrations/0007_auto_20141118_0925.py b/wagtail/tests/testapp/migrations/0007_auto_20141118_0925.py similarity index 100% rename from wagtail/tests/migrations/0007_auto_20141118_0925.py rename to wagtail/tests/testapp/migrations/0007_auto_20141118_0925.py diff --git a/wagtail/tests/migrations/0008_registerdecorator.py b/wagtail/tests/testapp/migrations/0008_registerdecorator.py similarity index 100% rename from wagtail/tests/migrations/0008_registerdecorator.py rename to wagtail/tests/testapp/migrations/0008_registerdecorator.py diff --git a/wagtail/tests/migrations/0009_eventpagechoosermodel.py b/wagtail/tests/testapp/migrations/0009_eventpagechoosermodel.py similarity index 100% rename from wagtail/tests/migrations/0009_eventpagechoosermodel.py rename to wagtail/tests/testapp/migrations/0009_eventpagechoosermodel.py diff --git a/wagtail/tests/migrations/0010_customimagewithadminformfields_customimagewithoutadminformfields.py b/wagtail/tests/testapp/migrations/0010_customimagewithadminformfields_customimagewithoutadminformfields.py similarity index 100% rename from wagtail/tests/migrations/0010_customimagewithadminformfields_customimagewithoutadminformfields.py rename to wagtail/tests/testapp/migrations/0010_customimagewithadminformfields_customimagewithoutadminformfields.py diff --git a/wagtail/tests/migrations/__init__.py b/wagtail/tests/testapp/migrations/__init__.py similarity index 100% rename from wagtail/tests/migrations/__init__.py rename to wagtail/tests/testapp/migrations/__init__.py diff --git a/wagtail/tests/models.py b/wagtail/tests/testapp/models.py similarity index 100% rename from wagtail/tests/models.py rename to wagtail/tests/testapp/models.py diff --git a/wagtail/tests/templates/tests/event_index.html b/wagtail/tests/testapp/templates/tests/event_index.html similarity index 100% rename from wagtail/tests/templates/tests/event_index.html rename to wagtail/tests/testapp/templates/tests/event_index.html diff --git a/wagtail/tests/templates/tests/event_page.html b/wagtail/tests/testapp/templates/tests/event_page.html similarity index 100% rename from wagtail/tests/templates/tests/event_page.html rename to wagtail/tests/testapp/templates/tests/event_page.html diff --git a/wagtail/tests/templates/tests/event_page_password_required.html b/wagtail/tests/testapp/templates/tests/event_page_password_required.html similarity index 100% rename from wagtail/tests/templates/tests/event_page_password_required.html rename to wagtail/tests/testapp/templates/tests/event_page_password_required.html diff --git a/wagtail/tests/templates/tests/form_page.html b/wagtail/tests/testapp/templates/tests/form_page.html similarity index 100% rename from wagtail/tests/templates/tests/form_page.html rename to wagtail/tests/testapp/templates/tests/form_page.html diff --git a/wagtail/tests/templates/tests/form_page_landing.html b/wagtail/tests/testapp/templates/tests/form_page_landing.html similarity index 100% rename from wagtail/tests/templates/tests/form_page_landing.html rename to wagtail/tests/testapp/templates/tests/form_page_landing.html diff --git a/wagtail/tests/templates/tests/includes/event_listing.html b/wagtail/tests/testapp/templates/tests/includes/event_listing.html similarity index 100% rename from wagtail/tests/templates/tests/includes/event_listing.html rename to wagtail/tests/testapp/templates/tests/includes/event_listing.html diff --git a/wagtail/tests/templates/tests/simple_page.html b/wagtail/tests/testapp/templates/tests/simple_page.html similarity index 100% rename from wagtail/tests/templates/tests/simple_page.html rename to wagtail/tests/testapp/templates/tests/simple_page.html diff --git a/wagtail/tests/wagtail_hooks.py b/wagtail/tests/testapp/wagtail_hooks.py similarity index 100% rename from wagtail/tests/wagtail_hooks.py rename to wagtail/tests/testapp/wagtail_hooks.py diff --git a/wagtail/wagtailadmin/tests/test_edit_handlers.py b/wagtail/wagtailadmin/tests/test_edit_handlers.py index 74128b3c5..8ff597d87 100644 --- a/wagtail/wagtailadmin/tests/test_edit_handlers.py +++ b/wagtail/wagtailadmin/tests/test_edit_handlers.py @@ -20,7 +20,7 @@ from wagtail.wagtailadmin.widgets import AdminPageChooser, AdminDateInput, Admin from wagtail.wagtailimages.edit_handlers import ImageChooserPanel from wagtail.wagtailcore.models import Page, Site from wagtail.wagtailcore.fields import RichTextArea -from wagtail.tests.models import PageChooserModel, EventPageChooserModel, EventPage, EventPageSpeaker, SimplePage +from wagtail.tests.testapp.models import PageChooserModel, EventPageChooserModel, EventPage, EventPageSpeaker, SimplePage from wagtail.tests.utils import WagtailTestUtils from wagtail.utils.deprecation import RemovedInWagtail12Warning diff --git a/wagtail/wagtailadmin/tests/test_page_chooser.py b/wagtail/wagtailadmin/tests/test_page_chooser.py index 834acde8c..3d67cbfaa 100644 --- a/wagtail/wagtailadmin/tests/test_page_chooser.py +++ b/wagtail/wagtailadmin/tests/test_page_chooser.py @@ -2,7 +2,7 @@ from django.test import TestCase from django.core.urlresolvers import reverse from wagtail.wagtailcore.models import Page -from wagtail.tests.models import SimplePage +from wagtail.tests.testapp.models import SimplePage from wagtail.tests.utils import WagtailTestUtils diff --git a/wagtail/wagtailadmin/tests/test_pages_views.py b/wagtail/wagtailadmin/tests/test_pages_views.py index 8bd3634a7..314a31aaf 100644 --- a/wagtail/wagtailadmin/tests/test_pages_views.py +++ b/wagtail/wagtailadmin/tests/test_pages_views.py @@ -11,7 +11,7 @@ from django.core.paginator import Paginator from django.db.models.signals import pre_delete, post_delete from django.utils import timezone -from wagtail.tests.models import ( +from wagtail.tests.testapp.models import ( SimplePage, EventPage, EventPageCarouselItem, StandardIndex, StandardChild, BusinessIndex, BusinessChild, BusinessSubIndex, diff --git a/wagtail/wagtailadmin/tests/test_privacy.py b/wagtail/wagtailadmin/tests/test_privacy.py index e49b81e0a..bda4fbd8c 100644 --- a/wagtail/wagtailadmin/tests/test_privacy.py +++ b/wagtail/wagtailadmin/tests/test_privacy.py @@ -2,7 +2,7 @@ from django.test import TestCase from django.core.urlresolvers import reverse from wagtail.wagtailcore.models import Page, PageViewRestriction -from wagtail.tests.models import SimplePage +from wagtail.tests.testapp.models import SimplePage from wagtail.tests.utils import WagtailTestUtils diff --git a/wagtail/wagtailcore/tests/test_management_commands.py b/wagtail/wagtailcore/tests/test_management_commands.py index 91fc727dc..01544f3c6 100644 --- a/wagtail/wagtailcore/tests/test_management_commands.py +++ b/wagtail/wagtailcore/tests/test_management_commands.py @@ -9,7 +9,7 @@ from django.db import models from wagtail.wagtailcore.models import Page, PageRevision from wagtail.wagtailcore.signals import page_published, page_unpublished -from wagtail.tests.models import SimplePage, EventPage +from wagtail.tests.testapp.models import SimplePage, EventPage class TestFixTreeCommand(TestCase): diff --git a/wagtail/wagtailcore/tests/test_page_model.py b/wagtail/wagtailcore/tests/test_page_model.py index a5d0a125b..58b8940de 100644 --- a/wagtail/wagtailcore/tests/test_page_model.py +++ b/wagtail/wagtailcore/tests/test_page_model.py @@ -11,7 +11,7 @@ from django.contrib.contenttypes.models import ContentType from django.contrib.auth import get_user_model from wagtail.wagtailcore.models import Page, Site -from wagtail.tests.models import EventPage, EventIndex, SimplePage, PageWithOldStyleRouteMethod, BusinessIndex, BusinessSubIndex, BusinessChild, StandardIndex +from wagtail.tests.testapp.models import EventPage, EventIndex, SimplePage, PageWithOldStyleRouteMethod, BusinessIndex, BusinessSubIndex, BusinessChild, StandardIndex class TestSiteRouting(TestCase): diff --git a/wagtail/wagtailcore/tests/test_page_permissions.py b/wagtail/wagtailcore/tests/test_page_permissions.py index bd2bd3f31..33dfc6e21 100644 --- a/wagtail/wagtailcore/tests/test_page_permissions.py +++ b/wagtail/wagtailcore/tests/test_page_permissions.py @@ -2,7 +2,7 @@ from django.test import TestCase from django.contrib.auth import get_user_model from wagtail.wagtailcore.models import Page, UserPagePermissionsProxy -from wagtail.tests.models import EventPage +from wagtail.tests.testapp.models import EventPage class TestPagePermission(TestCase): diff --git a/wagtail/wagtailcore/tests/test_page_queryset.py b/wagtail/wagtailcore/tests/test_page_queryset.py index c39358d93..3dce6c436 100644 --- a/wagtail/wagtailcore/tests/test_page_queryset.py +++ b/wagtail/wagtailcore/tests/test_page_queryset.py @@ -1,7 +1,7 @@ from django.test import TestCase from wagtail.wagtailcore.models import Page, PageViewRestriction -from wagtail.tests.models import EventPage +from wagtail.tests.testapp.models import EventPage class TestPageQuerySet(TestCase): diff --git a/wagtail/wagtailcore/tests/test_rich_text.py b/wagtail/wagtailcore/tests/test_rich_text.py index 8ffb917d8..bc12b4fd7 100644 --- a/wagtail/wagtailcore/tests/test_rich_text.py +++ b/wagtail/wagtailcore/tests/test_rich_text.py @@ -12,7 +12,7 @@ from bs4 import BeautifulSoup class TestPageLinkHandler(TestCase): - fixtures = ['wagtail/tests/fixtures/test.json'] + fixtures = ['test.json'] def test_get_db_attributes(self): soup = BeautifulSoup( diff --git a/wagtail/wagtailcore/tests/tests.py b/wagtail/wagtailcore/tests/tests.py index fd2e4de93..c71ab8492 100644 --- a/wagtail/wagtailcore/tests/tests.py +++ b/wagtail/wagtailcore/tests/tests.py @@ -7,7 +7,7 @@ from django.utils.safestring import SafeString from wagtail.wagtailcore.models import Page, Site from wagtail.wagtailcore.templatetags.wagtailcore_tags import richtext from wagtail.wagtailcore.utils import resolve_model_string -from wagtail.tests.models import SimplePage +from wagtail.tests.testapp.models import SimplePage class TestPageUrlTags(TestCase): diff --git a/wagtail/wagtaildocs/tests.py b/wagtail/wagtaildocs/tests.py index 863ad8e9c..a7943e492 100644 --- a/wagtail/wagtaildocs/tests.py +++ b/wagtail/wagtaildocs/tests.py @@ -13,7 +13,7 @@ from django.test.utils import override_settings from wagtail.tests.utils import WagtailTestUtils from wagtail.wagtailcore.models import Page -from wagtail.tests.models import EventPage, EventPageRelatedLink +from wagtail.tests.testapp.models import EventPage, EventPageRelatedLink from wagtail.wagtaildocs.models import Document from wagtail.wagtaildocs import models @@ -340,7 +340,7 @@ class TestDocumentFilenameProperties(TestCase): class TestUsageCount(TestCase, WagtailTestUtils): - fixtures = ['wagtail/tests/fixtures/test.json'] + fixtures = ['test.json'] def setUp(self): self.login() @@ -391,7 +391,7 @@ class TestUsageCount(TestCase, WagtailTestUtils): class TestGetUsage(TestCase, WagtailTestUtils): - fixtures = ['wagtail/tests/fixtures/test.json'] + fixtures = ['test.json'] def setUp(self): self.login() @@ -581,7 +581,7 @@ class TestServeView(TestCase): class TestDocumentRichTextLinkHandler(TestCase): - fixtures = ['wagtail/tests/fixtures/test.json'] + fixtures = ['test.json'] def test_get_db_attributes(self): soup = BeautifulSoup( diff --git a/wagtail/wagtailforms/tests.py b/wagtail/wagtailforms/tests.py index 25571bcc1..979f2243b 100644 --- a/wagtail/wagtailforms/tests.py +++ b/wagtail/wagtailforms/tests.py @@ -8,7 +8,7 @@ from django.core.urlresolvers import reverse from wagtail.wagtailcore.models import Page from wagtail.wagtailforms.models import FormSubmission from wagtail.wagtailforms.forms import FormBuilder -from wagtail.tests.models import FormPage, FormField +from wagtail.tests.testapp.models import FormPage, FormField class TestFormSubmission(TestCase): diff --git a/wagtail/wagtailimages/tests/test_models.py b/wagtail/wagtailimages/tests/test_models.py index 9abb3b093..5d96a2848 100644 --- a/wagtail/wagtailimages/tests/test_models.py +++ b/wagtail/wagtailimages/tests/test_models.py @@ -13,7 +13,7 @@ from django.db import connection from wagtail.tests.utils import WagtailTestUtils from wagtail.wagtailcore.models import Page -from wagtail.tests.models import EventPage, EventPageCarouselItem +from wagtail.tests.testapp.models import EventPage, EventPageCarouselItem from wagtail.wagtailimages.models import Rendition, Filter, SourceImageIOError from wagtail.wagtailimages.rect import Rect @@ -161,7 +161,7 @@ class TestRenditions(TestCase): class TestUsageCount(TestCase): - fixtures = ['wagtail/tests/fixtures/test.json'] + fixtures = ['test.json'] def setUp(self): self.image = Image.objects.create( @@ -184,7 +184,7 @@ class TestUsageCount(TestCase): class TestGetUsage(TestCase): - fixtures = ['wagtail/tests/fixtures/test.json'] + fixtures = ['test.json'] def setUp(self): self.image = Image.objects.create( diff --git a/wagtail/wagtailimages/tests/test_rich_text.py b/wagtail/wagtailimages/tests/test_rich_text.py index a9f91a468..473a6faab 100644 --- a/wagtail/wagtailimages/tests/test_rich_text.py +++ b/wagtail/wagtailimages/tests/test_rich_text.py @@ -7,8 +7,6 @@ from wagtail.wagtailimages.rich_text import ImageEmbedHandler class TestImageEmbedHandler(TestCase): - fixtures = ['wagtail/tests/fixtures/test.json'] - def test_get_db_attributes(self): soup = BeautifulSoup( 'foo' diff --git a/wagtail/wagtailimages/tests/tests.py b/wagtail/wagtailimages/tests/tests.py index f1f7bbbd9..3520d01d2 100644 --- a/wagtail/wagtailimages/tests/tests.py +++ b/wagtail/wagtailimages/tests/tests.py @@ -13,7 +13,7 @@ from django.db import models from taggit.forms import TagField, TagWidget from wagtail.utils.deprecation import RemovedInWagtail12Warning -from wagtail.tests.models import CustomImageWithAdminFormFields, CustomImageWithoutAdminFormFields +from wagtail.tests.testapp.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 diff --git a/wagtail/wagtailsearch/tests/test_backends.py b/wagtail/wagtailsearch/tests/test_backends.py index aad3ee8d8..c6c4b1fe6 100644 --- a/wagtail/wagtailsearch/tests/test_backends.py +++ b/wagtail/wagtailsearch/tests/test_backends.py @@ -8,7 +8,7 @@ from django.conf import settings from django.core import management from wagtail.tests.utils import WagtailTestUtils -from wagtail.tests import models +from wagtail.tests.testapp import models from wagtail.wagtailsearch.backends import get_search_backend, InvalidSearchBackendError from wagtail.wagtailsearch.backends.db import DBSearch diff --git a/wagtail/wagtailsearch/tests/test_elasticsearch_backend.py b/wagtail/wagtailsearch/tests/test_elasticsearch_backend.py index fadae9a36..41fcf22a1 100644 --- a/wagtail/wagtailsearch/tests/test_elasticsearch_backend.py +++ b/wagtail/wagtailsearch/tests/test_elasticsearch_backend.py @@ -8,7 +8,7 @@ import json from django.test import TestCase from django.db.models import Q -from wagtail.tests import models +from wagtail.tests.testapp import models from .test_backends import BackendTests diff --git a/wagtail/wagtailsearch/tests/test_frontend.py b/wagtail/wagtailsearch/tests/test_frontend.py index ba19b4396..e5c754d9b 100644 --- a/wagtail/wagtailsearch/tests/test_frontend.py +++ b/wagtail/wagtailsearch/tests/test_frontend.py @@ -5,7 +5,7 @@ from django.core import paginator from wagtail.wagtailcore.models import Page from wagtail.wagtailsearch.models import Query -from wagtail.tests.models import EventPage +from wagtail.tests.testapp.models import EventPage class TestSearchView(TestCase): diff --git a/wagtail/wagtailsearch/tests/test_indexed_class.py b/wagtail/wagtailsearch/tests/test_indexed_class.py index d4ed79b66..14d578602 100644 --- a/wagtail/wagtailsearch/tests/test_indexed_class.py +++ b/wagtail/wagtailsearch/tests/test_indexed_class.py @@ -3,7 +3,7 @@ import warnings from django.test import TestCase from wagtail.wagtailsearch import index -from wagtail.tests import models +from wagtail.tests.testapp import models from wagtail.tests.utils import WagtailTestUtils diff --git a/wagtail/wagtailsearch/tests/test_signal_handlers.py b/wagtail/wagtailsearch/tests/test_signal_handlers.py index ffdd143cf..535163a0e 100644 --- a/wagtail/wagtailsearch/tests/test_signal_handlers.py +++ b/wagtail/wagtailsearch/tests/test_signal_handlers.py @@ -1,7 +1,7 @@ from django.test import TestCase from wagtail.wagtailsearch import signal_handlers -from wagtail.tests import models +from wagtail.tests.testapp import models class TestGetIndexedInstance(TestCase): diff --git a/wagtail/wagtailsnippets/tests.py b/wagtail/wagtailsnippets/tests.py index 3f41b7e99..3d04b8619 100644 --- a/wagtail/wagtailsnippets/tests.py +++ b/wagtail/wagtailsnippets/tests.py @@ -2,10 +2,10 @@ from django.http import Http404 from django.test import TestCase from django.core.urlresolvers import reverse from django.db import models +from django.test.utils import override_settings from wagtail.tests.utils import WagtailTestUtils -from django.test.utils import override_settings -from wagtail.tests.models import Advert, AlphaSnippet, ZuluSnippet, SnippetChooserModel, RegisterDecorator, RegisterFunction +from wagtail.tests.testapp.models import Advert, AlphaSnippet, ZuluSnippet, SnippetChooserModel, RegisterDecorator, RegisterFunction from wagtail.wagtailsnippets.models import register_snippet, SNIPPET_MODELS from wagtail.wagtailsnippets.views.snippets import ( @@ -91,7 +91,7 @@ class TestSnippetCreateView(TestCase, WagtailTestUtils): class TestSnippetEditView(TestCase, WagtailTestUtils): - fixtures = ['wagtail/tests/fixtures/test.json'] + fixtures = ['test.json'] def setUp(self): self.test_snippet = Advert.objects.get(id=1) @@ -138,7 +138,7 @@ class TestSnippetEditView(TestCase, WagtailTestUtils): class TestSnippetDelete(TestCase, WagtailTestUtils): - fixtures = ['wagtail/tests/fixtures/test.json'] + fixtures = ['test.json'] def setUp(self): self.test_snippet = Advert.objects.get(id=1) @@ -160,7 +160,7 @@ class TestSnippetDelete(TestCase, WagtailTestUtils): class TestSnippetChooserPanel(TestCase): - fixtures = ['wagtail/tests/fixtures/test.json'] + fixtures = ['test.json'] def setUp(self): model = SnippetChooserModel @@ -213,7 +213,7 @@ class TestSnippetOrdering(TestCase): class TestUsageCount(TestCase): - fixtures = ['wagtail/tests/fixtures/test.json'] + fixtures = ['test.json'] @override_settings(WAGTAIL_USAGE_COUNT_ENABLED=True) def test_snippet_usage_count(self): @@ -222,7 +222,7 @@ class TestUsageCount(TestCase): class TestUsedBy(TestCase): - fixtures = ['wagtail/tests/fixtures/test.json'] + fixtures = ['test.json'] @override_settings(WAGTAIL_USAGE_COUNT_ENABLED=True) def test_snippet_used_by(self): @@ -231,7 +231,7 @@ class TestUsedBy(TestCase): class TestSnippetChoose(TestCase, WagtailTestUtils): - fixtures = ['wagtail/tests/fixtures/test.json'] + fixtures = ['test.json'] def setUp(self): self.login() @@ -255,7 +255,7 @@ class TestSnippetChoose(TestCase, WagtailTestUtils): class TestSnippetChosen(TestCase, WagtailTestUtils): - fixtures = ['wagtail/tests/fixtures/test.json'] + fixtures = ['test.json'] def setUp(self): self.login() From 83c7e242df221865f6743746e2466816d59852b4 Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Mon, 30 Mar 2015 12:57:37 +0100 Subject: [PATCH 02/27] Moved custom user model into its own app --- wagtail/tests/customuser/__init__.py | 0 .../customuser/migrations/0001_initial.py | 36 ++++++++++++++ .../migrations/0002_auto_20150330_0653.py | 26 ++++++++++ .../tests/customuser/migrations/__init__.py | 0 wagtail/tests/customuser/models.py | 47 +++++++++++++++++++ wagtail/tests/settings.py | 3 +- wagtail/tests/testapp/fixtures/test.json | 12 ++--- .../migrations/0011_auto_20150330_0653.py | 25 ++++++++++ wagtail/tests/testapp/models.py | 45 ------------------ 9 files changed, 142 insertions(+), 52 deletions(-) create mode 100644 wagtail/tests/customuser/__init__.py create mode 100644 wagtail/tests/customuser/migrations/0001_initial.py create mode 100644 wagtail/tests/customuser/migrations/0002_auto_20150330_0653.py create mode 100644 wagtail/tests/customuser/migrations/__init__.py create mode 100644 wagtail/tests/customuser/models.py create mode 100644 wagtail/tests/testapp/migrations/0011_auto_20150330_0653.py diff --git a/wagtail/tests/customuser/__init__.py b/wagtail/tests/customuser/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/wagtail/tests/customuser/migrations/0001_initial.py b/wagtail/tests/customuser/migrations/0001_initial.py new file mode 100644 index 000000000..c1dd942f5 --- /dev/null +++ b/wagtail/tests/customuser/migrations/0001_initial.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ('auth', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='CustomUser', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('password', models.CharField(max_length=128, verbose_name='password')), + ('last_login', models.DateTimeField(default=django.utils.timezone.now, verbose_name='last login')), + ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')), + ('username', models.CharField(unique=True, max_length=100)), + ('email', models.EmailField(max_length=255, blank=True)), + ('is_staff', models.BooleanField(default=True)), + ('is_active', models.BooleanField(default=True)), + ('first_name', models.CharField(max_length=50, blank=True)), + ('last_name', models.CharField(max_length=50, blank=True)), + ('groups', models.ManyToManyField(to='auth.Group', verbose_name='groups', blank=True)), + ('user_permissions', models.ManyToManyField(to='auth.Permission', verbose_name='user permissions', blank=True)), + ], + options={ + 'abstract': False, + }, + bases=(models.Model,), + ), + ] diff --git a/wagtail/tests/customuser/migrations/0002_auto_20150330_0653.py b/wagtail/tests/customuser/migrations/0002_auto_20150330_0653.py new file mode 100644 index 000000000..30be9eec6 --- /dev/null +++ b/wagtail/tests/customuser/migrations/0002_auto_20150330_0653.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('customuser', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='customuser', + name='groups', + field=models.ManyToManyField(to='auth.Group', verbose_name='groups', help_text='The groups this user belongs to. A user will get all permissions granted to each of his/her group.', related_name='user_set', blank=True, related_query_name='user'), + preserve_default=True, + ), + migrations.AlterField( + model_name='customuser', + name='user_permissions', + field=models.ManyToManyField(to='auth.Permission', verbose_name='user permissions', help_text='Specific permissions for this user.', related_name='user_set', blank=True, related_query_name='user'), + preserve_default=True, + ), + ] diff --git a/wagtail/tests/customuser/migrations/__init__.py b/wagtail/tests/customuser/migrations/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/wagtail/tests/customuser/models.py b/wagtail/tests/customuser/models.py new file mode 100644 index 000000000..cd09fa6e3 --- /dev/null +++ b/wagtail/tests/customuser/models.py @@ -0,0 +1,47 @@ +from django.db import models + +from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, BaseUserManager + + +class CustomUserManager(BaseUserManager): + def _create_user(self, username, email, password, + is_staff, is_superuser, **extra_fields): + """ + Creates and saves a User with the given username, email and password. + """ + if not username: + raise ValueError('The given username must be set') + email = self.normalize_email(email) + user = self.model(username=username, email=email, + is_staff=is_staff, is_active=True, + is_superuser=is_superuser, **extra_fields) + user.set_password(password) + user.save(using=self._db) + return user + + def create_user(self, username, email=None, password=None, **extra_fields): + return self._create_user(username, email, password, False, False, + **extra_fields) + + def create_superuser(self, username, email, password, **extra_fields): + return self._create_user(username, email, password, True, True, + **extra_fields) + + +class CustomUser(AbstractBaseUser, PermissionsMixin): + username = models.CharField(max_length=100, unique=True) + email = models.EmailField(max_length=255, blank=True) + is_staff = models.BooleanField(default=True) + is_active = models.BooleanField(default=True) + first_name = models.CharField(max_length=50, blank=True) + last_name = models.CharField(max_length=50, blank=True) + + USERNAME_FIELD = 'username' + + objects = CustomUserManager() + + def get_full_name(self): + return self.first_name + ' ' + self.last_name + + def get_short_name(self): + return self.first_name diff --git a/wagtail/tests/settings.py b/wagtail/tests/settings.py index f198e840d..a3b4ed2c6 100644 --- a/wagtail/tests/settings.py +++ b/wagtail/tests/settings.py @@ -77,6 +77,7 @@ INSTALLED_APPS = ( 'wagtail.contrib.wagtailroutablepage', 'wagtail.contrib.wagtailfrontendcache', 'wagtail.tests.testapp', + 'wagtail.tests.customuser', # Install wagtailredirects with its appconfig # Theres nothing special about wagtailredirects, we just need to have one @@ -110,7 +111,7 @@ WAGTAILSEARCH_BACKENDS = { } } -AUTH_USER_MODEL = 'tests.CustomUser' +AUTH_USER_MODEL = 'customuser.CustomUser' try: # Only add Elasticsearch backend if the elasticsearch-py library is installed diff --git a/wagtail/tests/testapp/fixtures/test.json b/wagtail/tests/testapp/fixtures/test.json index de8b1e27e..665006443 100644 --- a/wagtail/tests/testapp/fixtures/test.json +++ b/wagtail/tests/testapp/fixtures/test.json @@ -461,7 +461,7 @@ }, { "pk": 1, - "model": "tests.customuser", + "model": "customuser.customuser", "fields": { "username": "superuser", "first_name": "", @@ -478,7 +478,7 @@ }, { "pk": 2, - "model": "tests.customuser", + "model": "customuser.customuser", "fields": { "username": "eventeditor", "first_name": "", @@ -496,7 +496,7 @@ }, { "pk": 3, - "model": "tests.customuser", + "model": "customuser.customuser", "fields": { "username": "eventmoderator", "first_name": "", @@ -514,7 +514,7 @@ }, { "pk": 4, - "model": "tests.customuser", + "model": "customuser.customuser", "fields": { "username": "inactiveuser", "first_name": "", @@ -532,7 +532,7 @@ }, { "pk": 5, - "model": "tests.customuser", + "model": "customuser.customuser", "fields": { "username": "siteeditor", "first_name": "", @@ -550,7 +550,7 @@ }, { "pk": 6, - "model": "tests.customuser", + "model": "customuser.customuser", "fields": { "username": "admin_only_user", "first_name": "", diff --git a/wagtail/tests/testapp/migrations/0011_auto_20150330_0653.py b/wagtail/tests/testapp/migrations/0011_auto_20150330_0653.py new file mode 100644 index 000000000..0bc4febdc --- /dev/null +++ b/wagtail/tests/testapp/migrations/0011_auto_20150330_0653.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('tests', '0010_customimagewithadminformfields_customimagewithoutadminformfields'), + ] + + operations = [ + migrations.RemoveField( + model_name='customuser', + name='groups', + ), + migrations.RemoveField( + model_name='customuser', + name='user_permissions', + ), + migrations.DeleteModel( + name='CustomUser', + ), + ] diff --git a/wagtail/tests/testapp/models.py b/wagtail/tests/testapp/models.py index bb6f5f007..e1e627865 100644 --- a/wagtail/tests/testapp/models.py +++ b/wagtail/tests/testapp/models.py @@ -2,7 +2,6 @@ from __future__ import unicode_literals from django.db import models from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger -from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, BaseUserManager from django.utils.encoding import python_2_unicode_compatible from django.conf.urls import url from django.http import HttpResponse @@ -39,50 +38,6 @@ COMMON_PANELS = ( ) -class CustomUserManager(BaseUserManager): - def _create_user(self, username, email, password, - is_staff, is_superuser, **extra_fields): - """ - Creates and saves a User with the given username, email and password. - """ - if not username: - raise ValueError('The given username must be set') - email = self.normalize_email(email) - user = self.model(username=username, email=email, - is_staff=is_staff, is_active=True, - is_superuser=is_superuser, **extra_fields) - user.set_password(password) - user.save(using=self._db) - return user - - def create_user(self, username, email=None, password=None, **extra_fields): - return self._create_user(username, email, password, False, False, - **extra_fields) - - def create_superuser(self, username, email, password, **extra_fields): - return self._create_user(username, email, password, True, True, - **extra_fields) - - -class CustomUser(AbstractBaseUser, PermissionsMixin): - username = models.CharField(max_length=100, unique=True) - email = models.EmailField(max_length=255, blank=True) - is_staff = models.BooleanField(default=True) - is_active = models.BooleanField(default=True) - first_name = models.CharField(max_length=50, blank=True) - last_name = models.CharField(max_length=50, blank=True) - - USERNAME_FIELD = 'username' - - objects = CustomUserManager() - - def get_full_name(self): - return self.first_name + ' ' + self.last_name - - def get_short_name(self): - return self.first_name - - # Link fields class LinkFields(models.Model): From 89f540f8234c15b07dac9e245ebdf92479ae764a Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Mon, 30 Mar 2015 13:13:11 +0100 Subject: [PATCH 03/27] Moved snippets test models into separate app --- wagtail/tests/settings.py | 1 + wagtail/tests/snippets/__init__.py | 1 + wagtail/tests/snippets/apps.py | 7 +++ .../tests/snippets/migrations/0001_initial.py | 51 +++++++++++++++++++ wagtail/tests/snippets/migrations/__init__.py | 0 wagtail/tests/snippets/models.py | 39 ++++++++++++++ .../migrations/0012_auto_20150330_0709.py | 26 ++++++++++ wagtail/tests/testapp/models.py | 36 +------------ wagtail/wagtailsnippets/tests.py | 3 +- 9 files changed, 128 insertions(+), 36 deletions(-) create mode 100644 wagtail/tests/snippets/__init__.py create mode 100644 wagtail/tests/snippets/apps.py create mode 100644 wagtail/tests/snippets/migrations/0001_initial.py create mode 100644 wagtail/tests/snippets/migrations/__init__.py create mode 100644 wagtail/tests/snippets/models.py create mode 100644 wagtail/tests/testapp/migrations/0012_auto_20150330_0709.py diff --git a/wagtail/tests/settings.py b/wagtail/tests/settings.py index a3b4ed2c6..5ac3189a0 100644 --- a/wagtail/tests/settings.py +++ b/wagtail/tests/settings.py @@ -78,6 +78,7 @@ INSTALLED_APPS = ( 'wagtail.contrib.wagtailfrontendcache', 'wagtail.tests.testapp', 'wagtail.tests.customuser', + 'wagtail.tests.snippets', # Install wagtailredirects with its appconfig # Theres nothing special about wagtailredirects, we just need to have one diff --git a/wagtail/tests/snippets/__init__.py b/wagtail/tests/snippets/__init__.py new file mode 100644 index 000000000..96bbbaa54 --- /dev/null +++ b/wagtail/tests/snippets/__init__.py @@ -0,0 +1 @@ +default_app_config = 'wagtail.tests.snippets.apps.WagtailSnippetsTestsAppConfig' diff --git a/wagtail/tests/snippets/apps.py b/wagtail/tests/snippets/apps.py new file mode 100644 index 000000000..26004ec2b --- /dev/null +++ b/wagtail/tests/snippets/apps.py @@ -0,0 +1,7 @@ +from django.apps import AppConfig + + +class WagtailSnippetsTestsAppConfig(AppConfig): + name = 'wagtail.tests.snippets' + label = 'snippetstests' + verbose_name = "Wagtail snippets tests" diff --git a/wagtail/tests/snippets/migrations/0001_initial.py b/wagtail/tests/snippets/migrations/0001_initial.py new file mode 100644 index 000000000..b348bd2f5 --- /dev/null +++ b/wagtail/tests/snippets/migrations/0001_initial.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='AlphaSnippet', + fields=[ + ('id', models.AutoField(serialize=False, verbose_name='ID', auto_created=True, primary_key=True)), + ('text', models.CharField(max_length=255)), + ], + options={ + }, + bases=(models.Model,), + ), + migrations.CreateModel( + name='RegisterDecorator', + fields=[ + ('id', models.AutoField(serialize=False, verbose_name='ID', auto_created=True, primary_key=True)), + ], + options={ + }, + bases=(models.Model,), + ), + migrations.CreateModel( + name='RegisterFunction', + fields=[ + ('id', models.AutoField(serialize=False, verbose_name='ID', auto_created=True, primary_key=True)), + ], + options={ + }, + bases=(models.Model,), + ), + migrations.CreateModel( + name='ZuluSnippet', + fields=[ + ('id', models.AutoField(serialize=False, verbose_name='ID', auto_created=True, primary_key=True)), + ('text', models.CharField(max_length=255)), + ], + options={ + }, + bases=(models.Model,), + ), + ] diff --git a/wagtail/tests/snippets/migrations/__init__.py b/wagtail/tests/snippets/migrations/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/wagtail/tests/snippets/models.py b/wagtail/tests/snippets/models.py new file mode 100644 index 000000000..c3b9512a0 --- /dev/null +++ b/wagtail/tests/snippets/models.py @@ -0,0 +1,39 @@ +from django.db import models +from django.utils.encoding import python_2_unicode_compatible + +from wagtail.wagtailsnippets.models import register_snippet + + +# AlphaSnippet and ZuluSnippet are for testing ordering of +# snippets when registering. They are named as such to ensure +# thier ordering is clear. They are registered during testing +# to ensure specific [in]correct register ordering + +# AlphaSnippet is registered during TestSnippetOrdering +@python_2_unicode_compatible +class AlphaSnippet(models.Model): + text = models.CharField(max_length=255) + + def __str__(self): + return self.text + + +# ZuluSnippet is registered during TestSnippetOrdering +@python_2_unicode_compatible +class ZuluSnippet(models.Model): + text = models.CharField(max_length=255) + + def __str__(self): + return self.text + + +# Register model as snippet using register_snippet as both a function and a decorator + +class RegisterFunction(models.Model): + pass +register_snippet(RegisterFunction) + +@register_snippet +class RegisterDecorator(models.Model): + pass + diff --git a/wagtail/tests/testapp/migrations/0012_auto_20150330_0709.py b/wagtail/tests/testapp/migrations/0012_auto_20150330_0709.py new file mode 100644 index 000000000..79e0d1553 --- /dev/null +++ b/wagtail/tests/testapp/migrations/0012_auto_20150330_0709.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('tests', '0011_auto_20150330_0653'), + ] + + operations = [ + migrations.DeleteModel( + name='AlphaSnippet', + ), + migrations.DeleteModel( + name='RegisterDecorator', + ), + migrations.DeleteModel( + name='RegisterFunction', + ), + migrations.DeleteModel( + name='ZuluSnippet', + ), + ] diff --git a/wagtail/tests/testapp/models.py b/wagtail/tests/testapp/models.py index e1e627865..a13f83752 100644 --- a/wagtail/tests/testapp/models.py +++ b/wagtail/tests/testapp/models.py @@ -16,8 +16,8 @@ from wagtail.wagtailcore.fields import RichTextField from wagtail.wagtailadmin.edit_handlers import FieldPanel, MultiFieldPanel, InlinePanel, PageChooserPanel, TabbedInterface, ObjectList from wagtail.wagtailimages.edit_handlers import ImageChooserPanel from wagtail.wagtaildocs.edit_handlers import DocumentChooserPanel -from wagtail.wagtailforms.models import AbstractEmailForm, AbstractFormField from wagtail.wagtailsnippets.models import register_snippet +from wagtail.wagtailforms.models import AbstractEmailForm, AbstractFormField from wagtail.wagtailsnippets.edit_handlers import SnippetChooserPanel from wagtail.wagtailsearch import index from wagtail.contrib.wagtailroutablepage.models import RoutablePage @@ -320,29 +320,6 @@ class Advert(models.Model): register_snippet(Advert) -# AlphaSnippet and ZuluSnippet are for testing ordering of -# snippets when registering. They are named as such to ensure -# thier ordering is clear. They are registered during testing -# to ensure specific [in]correct register ordering - -# AlphaSnippet is registered during TestSnippetOrdering -@python_2_unicode_compatible -class AlphaSnippet(models.Model): - text = models.CharField(max_length=255) - - def __str__(self): - return self.text - - -# ZuluSnippet is registered during TestSnippetOrdering -@python_2_unicode_compatible -class ZuluSnippet(models.Model): - text = models.CharField(max_length=255) - - def __str__(self): - return self.text - - class StandardIndex(Page): """ Index for the site, not allowed to be placed anywhere """ parent_page_types = [] @@ -485,17 +462,6 @@ class SnippetChooserModel(models.Model): ] -# Register model as snippet using register_snippet as both a function and a decorator - -class RegisterFunction(models.Model): - pass -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) diff --git a/wagtail/wagtailsnippets/tests.py b/wagtail/wagtailsnippets/tests.py index 3d04b8619..996853dad 100644 --- a/wagtail/wagtailsnippets/tests.py +++ b/wagtail/wagtailsnippets/tests.py @@ -5,7 +5,8 @@ from django.db import models from django.test.utils import override_settings from wagtail.tests.utils import WagtailTestUtils -from wagtail.tests.testapp.models import Advert, AlphaSnippet, ZuluSnippet, SnippetChooserModel, RegisterDecorator, RegisterFunction +from wagtail.tests.testapp.models import Advert, SnippetChooserModel +from wagtail.tests.snippets.models import AlphaSnippet, ZuluSnippet, RegisterDecorator, RegisterFunction from wagtail.wagtailsnippets.models import register_snippet, SNIPPET_MODELS from wagtail.wagtailsnippets.views.snippets import ( From 5c3b0b5da2f4f3aa6d4373697ca08e89f1069008 Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Mon, 30 Mar 2015 13:24:18 +0100 Subject: [PATCH 04/27] Moved routablepage test model into its own app --- wagtail/contrib/wagtailroutablepage/tests.py | 2 +- wagtail/tests/routablepage/__init__.py | 1 + wagtail/tests/routablepage/apps.py | 7 +++++ .../routablepage/migrations/0001_initial.py | 25 ++++++++++++++++++ .../tests/routablepage/migrations/__init__.py | 0 wagtail/tests/routablepage/models.py | 26 +++++++++++++++++++ wagtail/tests/settings.py | 1 + .../migrations/0013_auto_20150330_0717.py | 21 +++++++++++++++ wagtail/tests/testapp/models.py | 24 ----------------- 9 files changed, 82 insertions(+), 25 deletions(-) create mode 100644 wagtail/tests/routablepage/__init__.py create mode 100644 wagtail/tests/routablepage/apps.py create mode 100644 wagtail/tests/routablepage/migrations/0001_initial.py create mode 100644 wagtail/tests/routablepage/migrations/__init__.py create mode 100644 wagtail/tests/routablepage/models.py create mode 100644 wagtail/tests/testapp/migrations/0013_auto_20150330_0717.py diff --git a/wagtail/contrib/wagtailroutablepage/tests.py b/wagtail/contrib/wagtailroutablepage/tests.py index 2e24cb3fe..2226b5cb5 100644 --- a/wagtail/contrib/wagtailroutablepage/tests.py +++ b/wagtail/contrib/wagtailroutablepage/tests.py @@ -1,7 +1,7 @@ from django.test import TestCase, RequestFactory from wagtail.wagtailcore.models import Page, Site -from wagtail.tests.testapp.models import RoutablePageTest, routable_page_external_view +from wagtail.tests.routablepage.models import RoutablePageTest, routable_page_external_view from wagtail.contrib.wagtailroutablepage.templatetags.wagtailroutablepage_tags import routablepageurl diff --git a/wagtail/tests/routablepage/__init__.py b/wagtail/tests/routablepage/__init__.py new file mode 100644 index 000000000..87fe2ba4a --- /dev/null +++ b/wagtail/tests/routablepage/__init__.py @@ -0,0 +1 @@ +default_app_config = 'wagtail.tests.routablepage.apps.WagtailRoutablePageTestsAppConfig' diff --git a/wagtail/tests/routablepage/apps.py b/wagtail/tests/routablepage/apps.py new file mode 100644 index 000000000..8a9f69be8 --- /dev/null +++ b/wagtail/tests/routablepage/apps.py @@ -0,0 +1,7 @@ +from django.apps import AppConfig + + +class WagtailRoutablePageTestsAppConfig(AppConfig): + name = 'wagtail.tests.routablepage' + label = 'routablepagetests' + verbose_name = "Wagtail routable page tests" diff --git a/wagtail/tests/routablepage/migrations/0001_initial.py b/wagtail/tests/routablepage/migrations/0001_initial.py new file mode 100644 index 000000000..6d5bdfa87 --- /dev/null +++ b/wagtail/tests/routablepage/migrations/0001_initial.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations +import wagtail.contrib.wagtailroutablepage.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('wagtailcore', '0013_update_golive_expire_help_text'), + ] + + operations = [ + migrations.CreateModel( + name='RoutablePageTest', + fields=[ + ('page_ptr', models.OneToOneField(to='wagtailcore.Page', serialize=False, auto_created=True, primary_key=True, parent_link=True)), + ], + options={ + 'abstract': False, + }, + bases=(wagtail.contrib.wagtailroutablepage.models.RoutablePageMixin, 'wagtailcore.page'), + ), + ] diff --git a/wagtail/tests/routablepage/migrations/__init__.py b/wagtail/tests/routablepage/migrations/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/wagtail/tests/routablepage/models.py b/wagtail/tests/routablepage/models.py new file mode 100644 index 000000000..51aee5b67 --- /dev/null +++ b/wagtail/tests/routablepage/models.py @@ -0,0 +1,26 @@ +from django.db import models +from django.http import HttpResponse +from django.conf.urls import url + +from wagtail.contrib.wagtailroutablepage.models import RoutablePage + + +def routable_page_external_view(request, arg): + return HttpResponse("EXTERNAL VIEW: " + arg) + +class RoutablePageTest(RoutablePage): + subpage_urls = ( + url(r'^$', 'main', name='main'), + url(r'^archive/year/(\d+)/$', 'archive_by_year', name='archive_by_year'), + url(r'^archive/author/(?P.+)/$', 'archive_by_author', name='archive_by_author'), + url(r'^external/(.+)/$', routable_page_external_view, name='external_view') + ) + + def archive_by_year(self, request, year): + return HttpResponse("ARCHIVE BY YEAR: " + str(year)) + + def archive_by_author(self, request, author_slug): + return HttpResponse("ARCHIVE BY AUTHOR: " + author_slug) + + def main(self, request): + return HttpResponse("MAIN VIEW") diff --git a/wagtail/tests/settings.py b/wagtail/tests/settings.py index 5ac3189a0..04d692151 100644 --- a/wagtail/tests/settings.py +++ b/wagtail/tests/settings.py @@ -79,6 +79,7 @@ INSTALLED_APPS = ( 'wagtail.tests.testapp', 'wagtail.tests.customuser', 'wagtail.tests.snippets', + 'wagtail.tests.routablepage', # Install wagtailredirects with its appconfig # Theres nothing special about wagtailredirects, we just need to have one diff --git a/wagtail/tests/testapp/migrations/0013_auto_20150330_0717.py b/wagtail/tests/testapp/migrations/0013_auto_20150330_0717.py new file mode 100644 index 000000000..8f27b4439 --- /dev/null +++ b/wagtail/tests/testapp/migrations/0013_auto_20150330_0717.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('wagtailcore', '0013_update_golive_expire_help_text'), + ('wagtailforms', '0001_initial'), + ('wagtailredirects', '0001_initial'), + ('wagtailsearch', '0001_initial'), + ('tests', '0012_auto_20150330_0709'), + ] + + operations = [ + migrations.DeleteModel( + name='RoutablePageTest', + ), + ] diff --git a/wagtail/tests/testapp/models.py b/wagtail/tests/testapp/models.py index a13f83752..c2bea54ae 100644 --- a/wagtail/tests/testapp/models.py +++ b/wagtail/tests/testapp/models.py @@ -3,8 +3,6 @@ from __future__ import unicode_literals from django.db import models from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger from django.utils.encoding import python_2_unicode_compatible -from django.conf.urls import url -from django.http import HttpResponse from taggit.models import TaggedItemBase @@ -20,7 +18,6 @@ from wagtail.wagtailsnippets.models import register_snippet from wagtail.wagtailforms.models import AbstractEmailForm, AbstractFormField 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 @@ -414,27 +411,6 @@ class SearchTestChild(SearchTest): ] -def routable_page_external_view(request, arg): - return HttpResponse("EXTERNAL VIEW: " + arg) - -class RoutablePageTest(RoutablePage): - subpage_urls = ( - url(r'^$', 'main', name='main'), - url(r'^archive/year/(\d+)/$', 'archive_by_year', name='archive_by_year'), - url(r'^archive/author/(?P.+)/$', 'archive_by_author', name='archive_by_author'), - url(r'^external/(.+)/$', routable_page_external_view, name='external_view') - ) - - def archive_by_year(self, request, year): - return HttpResponse("ARCHIVE BY YEAR: " + str(year)) - - def archive_by_author(self, request, author_slug): - return HttpResponse("ARCHIVE BY AUTHOR: " + author_slug) - - def main(self, request): - return HttpResponse("MAIN VIEW") - - class TaggedPageTag(TaggedItemBase): content_object = ParentalKey('tests.TaggedPage', related_name='tagged_items') From 1f8dc4bcfc3ff43d8816440468696e976f07dfae Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Mon, 30 Mar 2015 13:44:04 +0100 Subject: [PATCH 05/27] Moved search test models into their own app --- wagtail/tests/search/__init__.py | 1 + wagtail/tests/search/apps.py | 7 +++ .../tests/search/migrations/0001_initial.py | 38 +++++++++++++ wagtail/tests/search/migrations/__init__.py | 0 wagtail/tests/search/models.py | 54 +++++++++++++++++++ wagtail/tests/settings.py | 1 + .../migrations/0014_auto_20150330_0728.py | 24 +++++++++ wagtail/tests/testapp/models.py | 50 ----------------- wagtail/wagtailsearch/tests/test_backends.py | 2 +- .../tests/test_elasticsearch_backend.py | 52 +++++++++--------- .../wagtailsearch/tests/test_indexed_class.py | 6 +-- .../tests/test_signal_handlers.py | 2 +- 12 files changed, 156 insertions(+), 81 deletions(-) create mode 100644 wagtail/tests/search/__init__.py create mode 100644 wagtail/tests/search/apps.py create mode 100644 wagtail/tests/search/migrations/0001_initial.py create mode 100644 wagtail/tests/search/migrations/__init__.py create mode 100644 wagtail/tests/search/models.py create mode 100644 wagtail/tests/testapp/migrations/0014_auto_20150330_0728.py diff --git a/wagtail/tests/search/__init__.py b/wagtail/tests/search/__init__.py new file mode 100644 index 000000000..f28f75cff --- /dev/null +++ b/wagtail/tests/search/__init__.py @@ -0,0 +1 @@ +default_app_config = 'wagtail.tests.search.apps.WagtailSearchTestsAppConfig' diff --git a/wagtail/tests/search/apps.py b/wagtail/tests/search/apps.py new file mode 100644 index 000000000..a8e8c5ee3 --- /dev/null +++ b/wagtail/tests/search/apps.py @@ -0,0 +1,7 @@ +from django.apps import AppConfig + + +class WagtailSearchTestsAppConfig(AppConfig): + name = 'wagtail.tests.search' + label = 'searchtests' + verbose_name = "Wagtail search tests" diff --git a/wagtail/tests/search/migrations/0001_initial.py b/wagtail/tests/search/migrations/0001_initial.py new file mode 100644 index 000000000..6359e5355 --- /dev/null +++ b/wagtail/tests/search/migrations/0001_initial.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations +import wagtail.wagtailsearch.index + + +class Migration(migrations.Migration): + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='SearchTest', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, verbose_name='ID', serialize=False)), + ('title', models.CharField(max_length=255)), + ('content', models.TextField()), + ('live', models.BooleanField(default=False)), + ('published_date', models.DateField(null=True)), + ], + options={ + }, + bases=(models.Model, wagtail.wagtailsearch.index.Indexed), + ), + migrations.CreateModel( + name='SearchTestChild', + fields=[ + ('searchtest_ptr', models.OneToOneField(primary_key=True, serialize=False, parent_link=True, to='searchtests.SearchTest', auto_created=True)), + ('subtitle', models.CharField(null=True, max_length=255, blank=True)), + ('extra_content', models.TextField()), + ], + options={ + }, + bases=('searchtests.searchtest',), + ), + ] diff --git a/wagtail/tests/search/migrations/__init__.py b/wagtail/tests/search/migrations/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/wagtail/tests/search/models.py b/wagtail/tests/search/models.py new file mode 100644 index 000000000..d5f646576 --- /dev/null +++ b/wagtail/tests/search/models.py @@ -0,0 +1,54 @@ +from django.db import models + +from wagtail.wagtailsearch import index + + +class SearchTest(models.Model, index.Indexed): + title = models.CharField(max_length=255) + content = models.TextField() + live = models.BooleanField(default=False) + published_date = models.DateField(null=True) + + search_fields = [ + index.SearchField('title', partial_match=True), + index.SearchField('content'), + index.SearchField('callable_indexed_field'), + index.FilterField('title'), + index.FilterField('live'), + index.FilterField('published_date'), + ] + + def callable_indexed_field(self): + return "Callable" + + @classmethod + def get_indexed_objects(cls): + indexed_objects = super(SearchTest, cls).get_indexed_objects() + + # Exclude SearchTests that have a SearchTestChild to stop update_index creating duplicates + if cls is SearchTest: + indexed_objects = indexed_objects.exclude( + id__in=SearchTestChild.objects.all().values_list('searchtest_ptr_id', flat=True) + ) + + # Exclude SearchTests that have the title "Don't index me!" + indexed_objects = indexed_objects.exclude(title="Don't index me!") + + return indexed_objects + + def get_indexed_instance(self): + # Check if there is a SearchTestChild that descends from this + child = SearchTestChild.objects.filter(searchtest_ptr_id=self.id).first() + + # Return the child if there is one, otherwise return self + return child or self + + +class SearchTestChild(SearchTest): + subtitle = models.CharField(max_length=255, null=True, blank=True) + extra_content = models.TextField() + + search_fields = SearchTest.search_fields + [ + index.SearchField('subtitle', partial_match=True), + index.SearchField('extra_content'), + ] diff --git a/wagtail/tests/settings.py b/wagtail/tests/settings.py index 04d692151..50ffb6ffa 100644 --- a/wagtail/tests/settings.py +++ b/wagtail/tests/settings.py @@ -80,6 +80,7 @@ INSTALLED_APPS = ( 'wagtail.tests.customuser', 'wagtail.tests.snippets', 'wagtail.tests.routablepage', + 'wagtail.tests.search', # Install wagtailredirects with its appconfig # Theres nothing special about wagtailredirects, we just need to have one diff --git a/wagtail/tests/testapp/migrations/0014_auto_20150330_0728.py b/wagtail/tests/testapp/migrations/0014_auto_20150330_0728.py new file mode 100644 index 000000000..3217ac402 --- /dev/null +++ b/wagtail/tests/testapp/migrations/0014_auto_20150330_0728.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('tests', '0013_auto_20150330_0717'), + ] + + operations = [ + migrations.RemoveField( + model_name='searchtestchild', + name='searchtest_ptr', + ), + migrations.DeleteModel( + name='SearchTestChild', + ), + migrations.DeleteModel( + name='SearchTest', + ), + ] diff --git a/wagtail/tests/testapp/models.py b/wagtail/tests/testapp/models.py index c2bea54ae..628997b00 100644 --- a/wagtail/tests/testapp/models.py +++ b/wagtail/tests/testapp/models.py @@ -361,56 +361,6 @@ class BusinessChild(Page): parent_page_types = ['tests.BusinessIndex', BusinessSubIndex] -class SearchTest(models.Model, index.Indexed): - title = models.CharField(max_length=255) - content = models.TextField() - live = models.BooleanField(default=False) - published_date = models.DateField(null=True) - - search_fields = [ - index.SearchField('title', partial_match=True), - index.SearchField('content'), - index.SearchField('callable_indexed_field'), - index.FilterField('title'), - index.FilterField('live'), - index.FilterField('published_date'), - ] - - def callable_indexed_field(self): - return "Callable" - - @classmethod - def get_indexed_objects(cls): - indexed_objects = super(SearchTest, cls).get_indexed_objects() - - # Exclude SearchTests that have a SearchTestChild to stop update_index creating duplicates - if cls is SearchTest: - indexed_objects = indexed_objects.exclude( - id__in=SearchTestChild.objects.all().values_list('searchtest_ptr_id', flat=True) - ) - - # Exclude SearchTests that have the title "Don't index me!" - indexed_objects = indexed_objects.exclude(title="Don't index me!") - - return indexed_objects - - def get_indexed_instance(self): - # Check if there is a SearchTestChild that descends from this - child = SearchTestChild.objects.filter(searchtest_ptr_id=self.id).first() - - # Return the child if there is one, otherwise return self - return child or self - -class SearchTestChild(SearchTest): - subtitle = models.CharField(max_length=255, null=True, blank=True) - extra_content = models.TextField() - - search_fields = SearchTest.search_fields + [ - index.SearchField('subtitle', partial_match=True), - index.SearchField('extra_content'), - ] - - class TaggedPageTag(TaggedItemBase): content_object = ParentalKey('tests.TaggedPage', related_name='tagged_items') diff --git a/wagtail/wagtailsearch/tests/test_backends.py b/wagtail/wagtailsearch/tests/test_backends.py index c6c4b1fe6..fc181d6f3 100644 --- a/wagtail/wagtailsearch/tests/test_backends.py +++ b/wagtail/wagtailsearch/tests/test_backends.py @@ -8,7 +8,7 @@ from django.conf import settings from django.core import management from wagtail.tests.utils import WagtailTestUtils -from wagtail.tests.testapp import models +from wagtail.tests.search import models from wagtail.wagtailsearch.backends import get_search_backend, InvalidSearchBackendError from wagtail.wagtailsearch.backends.db import DBSearch diff --git a/wagtail/wagtailsearch/tests/test_elasticsearch_backend.py b/wagtail/wagtailsearch/tests/test_elasticsearch_backend.py index 41fcf22a1..8e0be1f3a 100644 --- a/wagtail/wagtailsearch/tests/test_elasticsearch_backend.py +++ b/wagtail/wagtailsearch/tests/test_elasticsearch_backend.py @@ -8,7 +8,7 @@ import json from django.test import TestCase from django.db.models import Q -from wagtail.tests.testapp import models +from wagtail.tests.search import models from .test_backends import BackendTests @@ -186,7 +186,7 @@ class TestElasticSearchQuery(TestCase): query = self.ElasticSearchQuery(models.SearchTest.objects.all(), "Hello") # Check it - expected_result = {'filtered': {'filter': {'prefix': {'content_type': 'tests_searchtest'}}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}} + expected_result = {'filtered': {'filter': {'prefix': {'content_type': 'searchtests_searchtest'}}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}} self.assertDictEqual(query.to_es(), expected_result) def test_none_query_string(self): @@ -194,7 +194,7 @@ class TestElasticSearchQuery(TestCase): query = self.ElasticSearchQuery(models.SearchTest.objects.all(), None) # Check it - expected_result = {'filtered': {'filter': {'prefix': {'content_type': 'tests_searchtest'}}, 'query': {'match_all': {}}}} + expected_result = {'filtered': {'filter': {'prefix': {'content_type': 'searchtests_searchtest'}}, 'query': {'match_all': {}}}} self.assertDictEqual(query.to_es(), expected_result) def test_filter(self): @@ -202,7 +202,7 @@ class TestElasticSearchQuery(TestCase): query = self.ElasticSearchQuery(models.SearchTest.objects.filter(title="Test"), "Hello") # Check it - expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'tests_searchtest'}}, {'term': {'title_filter': 'Test'}}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}} + expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'searchtests_searchtest'}}, {'term': {'title_filter': 'Test'}}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}} self.assertDictEqual(query.to_es(), expected_result) def test_and_filter(self): @@ -210,7 +210,7 @@ class TestElasticSearchQuery(TestCase): query = self.ElasticSearchQuery(models.SearchTest.objects.filter(title="Test", live=True), "Hello") # Check it - expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'tests_searchtest'}}, {'and': [{'term': {'live_filter': True}}, {'term': {'title_filter': 'Test'}}]}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}} + expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'searchtests_searchtest'}}, {'and': [{'term': {'live_filter': True}}, {'term': {'title_filter': 'Test'}}]}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}} # Make sure field filters are sorted (as they can be in any order which may cause false positives) query = query.to_es() @@ -229,7 +229,7 @@ class TestElasticSearchQuery(TestCase): field_filters[:] = sorted(field_filters, key=lambda f: list(f['term'].keys())[0]) # Check it - expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'tests_searchtest'}}, {'or': [{'term': {'live_filter': True}}, {'term': {'title_filter': 'Test'}}]}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}} + expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'searchtests_searchtest'}}, {'or': [{'term': {'live_filter': True}}, {'term': {'title_filter': 'Test'}}]}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}} self.assertDictEqual(query, expected_result) def test_negated_filter(self): @@ -237,7 +237,7 @@ class TestElasticSearchQuery(TestCase): query = self.ElasticSearchQuery(models.SearchTest.objects.exclude(live=True), "Hello") # Check it - expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'tests_searchtest'}}, {'not': {'term': {'live_filter': True}}}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}} + expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'searchtests_searchtest'}}, {'not': {'term': {'live_filter': True}}}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}} self.assertDictEqual(query.to_es(), expected_result) def test_fields(self): @@ -245,7 +245,7 @@ class TestElasticSearchQuery(TestCase): query = self.ElasticSearchQuery(models.SearchTest.objects.all(), "Hello", fields=['title']) # Check it - expected_result = {'filtered': {'filter': {'prefix': {'content_type': 'tests_searchtest'}}, 'query': {'match': {'title': 'Hello'}}}} + expected_result = {'filtered': {'filter': {'prefix': {'content_type': 'searchtests_searchtest'}}, 'query': {'match': {'title': 'Hello'}}}} self.assertDictEqual(query.to_es(), expected_result) def test_exact_lookup(self): @@ -253,7 +253,7 @@ class TestElasticSearchQuery(TestCase): query = self.ElasticSearchQuery(models.SearchTest.objects.filter(title__exact="Test"), "Hello") # Check it - expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'tests_searchtest'}}, {'term': {'title_filter': 'Test'}}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}} + expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'searchtests_searchtest'}}, {'term': {'title_filter': 'Test'}}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}} self.assertDictEqual(query.to_es(), expected_result) def test_none_lookup(self): @@ -261,7 +261,7 @@ class TestElasticSearchQuery(TestCase): query = self.ElasticSearchQuery(models.SearchTest.objects.filter(title=None), "Hello") # Check it - expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'tests_searchtest'}}, {'missing': {'field': 'title_filter'}}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}} + expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'searchtests_searchtest'}}, {'missing': {'field': 'title_filter'}}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}} self.assertDictEqual(query.to_es(), expected_result) def test_isnull_true_lookup(self): @@ -269,7 +269,7 @@ class TestElasticSearchQuery(TestCase): query = self.ElasticSearchQuery(models.SearchTest.objects.filter(title__isnull=True), "Hello") # Check it - expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'tests_searchtest'}}, {'missing': {'field': 'title_filter'}}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}} + expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'searchtests_searchtest'}}, {'missing': {'field': 'title_filter'}}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}} self.assertDictEqual(query.to_es(), expected_result) def test_isnull_false_lookup(self): @@ -277,7 +277,7 @@ class TestElasticSearchQuery(TestCase): query = self.ElasticSearchQuery(models.SearchTest.objects.filter(title__isnull=False), "Hello") # Check it - expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'tests_searchtest'}}, {'not': {'missing': {'field': 'title_filter'}}}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}} + expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'searchtests_searchtest'}}, {'not': {'missing': {'field': 'title_filter'}}}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}} self.assertDictEqual(query.to_es(), expected_result) def test_startswith_lookup(self): @@ -285,7 +285,7 @@ class TestElasticSearchQuery(TestCase): query = self.ElasticSearchQuery(models.SearchTest.objects.filter(title__startswith="Test"), "Hello") # Check it - expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'tests_searchtest'}}, {'prefix': {'title_filter': 'Test'}}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}} + expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'searchtests_searchtest'}}, {'prefix': {'title_filter': 'Test'}}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}} self.assertDictEqual(query.to_es(), expected_result) def test_gt_lookup(self): @@ -295,7 +295,7 @@ class TestElasticSearchQuery(TestCase): query = self.ElasticSearchQuery(models.SearchTest.objects.filter(published_date__gt=datetime.datetime(2014, 4, 29)), "Hello") # Check it - expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'tests_searchtest'}}, {'range': {'published_date_filter': {'gt': '2014-04-29'}}}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}} + expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'searchtests_searchtest'}}, {'range': {'published_date_filter': {'gt': '2014-04-29'}}}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}} self.assertDictEqual(query.to_es(), expected_result) def test_lt_lookup(self): @@ -303,7 +303,7 @@ class TestElasticSearchQuery(TestCase): query = self.ElasticSearchQuery(models.SearchTest.objects.filter(published_date__lt=datetime.datetime(2014, 4, 29)), "Hello") # Check it - expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'tests_searchtest'}}, {'range': {'published_date_filter': {'lt': '2014-04-29'}}}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}} + expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'searchtests_searchtest'}}, {'range': {'published_date_filter': {'lt': '2014-04-29'}}}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}} self.assertDictEqual(query.to_es(), expected_result) def test_gte_lookup(self): @@ -311,7 +311,7 @@ class TestElasticSearchQuery(TestCase): query = self.ElasticSearchQuery(models.SearchTest.objects.filter(published_date__gte=datetime.datetime(2014, 4, 29)), "Hello") # Check it - expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'tests_searchtest'}}, {'range': {'published_date_filter': {'gte': '2014-04-29'}}}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}} + expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'searchtests_searchtest'}}, {'range': {'published_date_filter': {'gte': '2014-04-29'}}}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}} self.assertDictEqual(query.to_es(), expected_result) def test_lte_lookup(self): @@ -319,7 +319,7 @@ class TestElasticSearchQuery(TestCase): query = self.ElasticSearchQuery(models.SearchTest.objects.filter(published_date__lte=datetime.datetime(2014, 4, 29)), "Hello") # Check it - expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'tests_searchtest'}}, {'range': {'published_date_filter': {'lte': '2014-04-29'}}}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}} + expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'searchtests_searchtest'}}, {'range': {'published_date_filter': {'lte': '2014-04-29'}}}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}} self.assertDictEqual(query.to_es(), expected_result) def test_range_lookup(self): @@ -330,7 +330,7 @@ class TestElasticSearchQuery(TestCase): query = self.ElasticSearchQuery(models.SearchTest.objects.filter(published_date__range=(start_date, end_date)), "Hello") # Check it - expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'tests_searchtest'}}, {'range': {'published_date_filter': {'gte': '2014-04-29', 'lte': '2014-08-19'}}}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}} + expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'searchtests_searchtest'}}, {'range': {'published_date_filter': {'gte': '2014-04-29', 'lte': '2014-08-19'}}}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}} self.assertDictEqual(query.to_es(), expected_result) @@ -358,7 +358,7 @@ class TestElasticSearchMapping(TestCase): self.obj.save() def test_get_document_type(self): - self.assertEqual(self.es_mapping.get_document_type(), 'tests_searchtest') + self.assertEqual(self.es_mapping.get_document_type(), 'searchtests_searchtest') def test_get_mapping(self): # Build mapping @@ -366,7 +366,7 @@ class TestElasticSearchMapping(TestCase): # Check expected_result = { - 'tests_searchtest': { + 'searchtests_searchtest': { 'properties': { 'pk': {'index': 'not_analyzed', 'type': 'string', 'store': 'yes', 'include_in_all': False}, 'content_type': {'index': 'not_analyzed', 'type': 'string', 'include_in_all': False}, @@ -384,7 +384,7 @@ class TestElasticSearchMapping(TestCase): self.assertDictEqual(mapping, expected_result) def test_get_document_id(self): - self.assertEqual(self.es_mapping.get_document_id(self.obj), 'tests_searchtest:' + str(self.obj.pk)) + self.assertEqual(self.es_mapping.get_document_id(self.obj), 'searchtests_searchtest:' + str(self.obj.pk)) def test_get_document(self): # Get document @@ -393,7 +393,7 @@ class TestElasticSearchMapping(TestCase): # Check expected_result = { 'pk': str(self.obj.pk), - 'content_type': 'tests_searchtest', + 'content_type': 'searchtests_searchtest', '_partials': ['Hello'], 'live_filter': False, 'published_date_filter': None, @@ -430,7 +430,7 @@ class TestElasticSearchMappingInheritance(TestCase): self.obj.save() def test_get_document_type(self): - self.assertEqual(self.es_mapping.get_document_type(), 'tests_searchtest_tests_searchtestchild') + self.assertEqual(self.es_mapping.get_document_type(), 'searchtests_searchtest_searchtests_searchtestchild') def test_get_mapping(self): # Build mapping @@ -438,7 +438,7 @@ class TestElasticSearchMappingInheritance(TestCase): # Check expected_result = { - 'tests_searchtest_tests_searchtestchild': { + 'searchtests_searchtest_searchtests_searchtestchild': { 'properties': { # New 'extra_content': {'type': 'string', 'include_in_all': True}, @@ -464,7 +464,7 @@ class TestElasticSearchMappingInheritance(TestCase): # This must be tests_searchtest instead of 'tests_searchtest_tests_searchtestchild' # as it uses the contents base content type name. # This prevents the same object being accidentally indexed twice. - self.assertEqual(self.es_mapping.get_document_id(self.obj), 'tests_searchtest:' + str(self.obj.pk)) + self.assertEqual(self.es_mapping.get_document_id(self.obj), 'searchtests_searchtest:' + str(self.obj.pk)) def test_get_document(self): # Build document @@ -481,7 +481,7 @@ class TestElasticSearchMappingInheritance(TestCase): 'subtitle': 'World', # Changed - 'content_type': 'tests_searchtest_tests_searchtestchild', + 'content_type': 'searchtests_searchtest_searchtests_searchtestchild', # Inherited 'pk': str(self.obj.pk), diff --git a/wagtail/wagtailsearch/tests/test_indexed_class.py b/wagtail/wagtailsearch/tests/test_indexed_class.py index 14d578602..91cc2b51a 100644 --- a/wagtail/wagtailsearch/tests/test_indexed_class.py +++ b/wagtail/wagtailsearch/tests/test_indexed_class.py @@ -3,18 +3,18 @@ import warnings from django.test import TestCase from wagtail.wagtailsearch import index -from wagtail.tests.testapp import models +from wagtail.tests.search import models from wagtail.tests.utils import WagtailTestUtils class TestContentTypeNames(TestCase): def test_base_content_type_name(self): name = models.SearchTestChild.indexed_get_toplevel_content_type() - self.assertEqual(name, 'tests_searchtest') + self.assertEqual(name, 'searchtests_searchtest') def test_qualified_content_type_name(self): name = models.SearchTestChild.indexed_get_content_type() - self.assertEqual(name, 'tests_searchtest_tests_searchtestchild') + self.assertEqual(name, 'searchtests_searchtest_searchtests_searchtestchild') class TestSearchFields(TestCase): diff --git a/wagtail/wagtailsearch/tests/test_signal_handlers.py b/wagtail/wagtailsearch/tests/test_signal_handlers.py index 535163a0e..001b798f9 100644 --- a/wagtail/wagtailsearch/tests/test_signal_handlers.py +++ b/wagtail/wagtailsearch/tests/test_signal_handlers.py @@ -1,7 +1,7 @@ from django.test import TestCase from wagtail.wagtailsearch import signal_handlers -from wagtail.tests.testapp import models +from wagtail.tests.search import models class TestGetIndexedInstance(TestCase): From 440aa0742a1c0d83451e5c823b70b516764014e5 Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Mon, 30 Mar 2015 13:48:10 +0100 Subject: [PATCH 06/27] Recreated testapp migrations --- .../tests/testapp/migrations/0001_initial.py | 382 ++++++++++++++++- .../migrations/0002_auto_20140827_0908.py | 386 ------------------ .../migrations/0003_auto_20140905_0634.py | 20 - .../migrations/0004_auto_20141008_0420.py | 20 - .../migrations/0005_auto_20141008_0122.py | 35 -- .../migrations/0005_auto_20141113_0642.py | 27 -- .../tests/testapp/migrations/0006_merge.py | 15 - .../migrations/0007_auto_20141118_0925.py | 26 -- .../migrations/0008_registerdecorator.py | 32 -- .../migrations/0009_eventpagechoosermodel.py | 24 -- ...ields_customimagewithoutadminformfields.py | 65 --- .../migrations/0011_auto_20150330_0653.py | 25 -- .../migrations/0012_auto_20150330_0709.py | 26 -- .../migrations/0013_auto_20150330_0717.py | 21 - .../migrations/0014_auto_20150330_0728.py | 24 -- 15 files changed, 367 insertions(+), 761 deletions(-) delete mode 100644 wagtail/tests/testapp/migrations/0002_auto_20140827_0908.py delete mode 100644 wagtail/tests/testapp/migrations/0003_auto_20140905_0634.py delete mode 100644 wagtail/tests/testapp/migrations/0004_auto_20141008_0420.py delete mode 100644 wagtail/tests/testapp/migrations/0005_auto_20141008_0122.py delete mode 100644 wagtail/tests/testapp/migrations/0005_auto_20141113_0642.py delete mode 100644 wagtail/tests/testapp/migrations/0006_merge.py delete mode 100644 wagtail/tests/testapp/migrations/0007_auto_20141118_0925.py delete mode 100644 wagtail/tests/testapp/migrations/0008_registerdecorator.py delete mode 100644 wagtail/tests/testapp/migrations/0009_eventpagechoosermodel.py delete mode 100644 wagtail/tests/testapp/migrations/0010_customimagewithadminformfields_customimagewithoutadminformfields.py delete mode 100644 wagtail/tests/testapp/migrations/0011_auto_20150330_0653.py delete mode 100644 wagtail/tests/testapp/migrations/0012_auto_20150330_0709.py delete mode 100644 wagtail/tests/testapp/migrations/0013_auto_20150330_0717.py delete mode 100644 wagtail/tests/testapp/migrations/0014_auto_20150330_0728.py diff --git a/wagtail/tests/testapp/migrations/0001_initial.py b/wagtail/tests/testapp/migrations/0001_initial.py index c1dd942f5..0c3af9b25 100644 --- a/wagtail/tests/testapp/migrations/0001_initial.py +++ b/wagtail/tests/testapp/migrations/0001_initial.py @@ -2,35 +2,387 @@ from __future__ import unicode_literals from django.db import models, migrations -import django.utils.timezone +import django.db.models.deletion +from django.conf import settings +import modelcluster.tags +import wagtail.wagtailimages.models +import wagtail.wagtailadmin.taggable +import modelcluster.fields +import wagtail.wagtailcore.fields +import taggit.managers class Migration(migrations.Migration): dependencies = [ - ('auth', '0001_initial'), + ('wagtailcore', '0013_update_golive_expire_help_text'), + ('wagtaildocs', '0002_initial_data'), + ('taggit', '0001_initial'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('wagtailimages', '0005_make_filter_spec_unique'), ] operations = [ migrations.CreateModel( - name='CustomUser', + name='Advert', fields=[ - ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('password', models.CharField(max_length=128, verbose_name='password')), - ('last_login', models.DateTimeField(default=django.utils.timezone.now, verbose_name='last login')), - ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')), - ('username', models.CharField(unique=True, max_length=100)), - ('email', models.EmailField(max_length=255, blank=True)), - ('is_staff', models.BooleanField(default=True)), - ('is_active', models.BooleanField(default=True)), - ('first_name', models.CharField(max_length=50, blank=True)), - ('last_name', models.CharField(max_length=50, blank=True)), - ('groups', models.ManyToManyField(to='auth.Group', verbose_name='groups', blank=True)), - ('user_permissions', models.ManyToManyField(to='auth.Permission', verbose_name='user permissions', blank=True)), + ('id', models.AutoField(serialize=False, auto_created=True, verbose_name='ID', primary_key=True)), + ('url', models.URLField(blank=True, null=True)), + ('text', models.CharField(max_length=255)), + ], + options={ + }, + bases=(models.Model,), + ), + migrations.CreateModel( + name='AdvertPlacement', + fields=[ + ('id', models.AutoField(serialize=False, auto_created=True, verbose_name='ID', primary_key=True)), + ('colour', models.CharField(max_length=255)), + ('advert', models.ForeignKey(to='tests.Advert', related_name='+')), + ], + options={ + }, + bases=(models.Model,), + ), + migrations.CreateModel( + name='BusinessChild', + fields=[ + ('page_ptr', models.OneToOneField(parent_link=True, primary_key=True, to='wagtailcore.Page', auto_created=True, serialize=False)), + ], + options={ + 'abstract': False, + }, + bases=('wagtailcore.page',), + ), + migrations.CreateModel( + name='BusinessIndex', + fields=[ + ('page_ptr', models.OneToOneField(parent_link=True, primary_key=True, to='wagtailcore.Page', auto_created=True, serialize=False)), + ], + options={ + 'abstract': False, + }, + bases=('wagtailcore.page',), + ), + migrations.CreateModel( + name='BusinessSubIndex', + fields=[ + ('page_ptr', models.OneToOneField(parent_link=True, primary_key=True, to='wagtailcore.Page', auto_created=True, serialize=False)), + ], + options={ + 'abstract': False, + }, + bases=('wagtailcore.page',), + ), + migrations.CreateModel( + name='CustomImageWithAdminFormFields', + fields=[ + ('id', models.AutoField(serialize=False, auto_created=True, verbose_name='ID', primary_key=True)), + ('title', models.CharField(max_length=255, verbose_name='Title')), + ('file', models.ImageField(width_field='width', height_field='height', upload_to=wagtail.wagtailimages.models.get_upload_to, verbose_name='File')), + ('width', models.IntegerField(editable=False)), + ('height', models.IntegerField(editable=False)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('focal_point_x', models.PositiveIntegerField(blank=True, null=True)), + ('focal_point_y', models.PositiveIntegerField(blank=True, null=True)), + ('focal_point_width', models.PositiveIntegerField(blank=True, null=True)), + ('focal_point_height', models.PositiveIntegerField(blank=True, null=True)), + ('caption', models.CharField(max_length=255)), + ('not_editable_field', models.CharField(max_length=255)), + ('tags', taggit.managers.TaggableManager(verbose_name='Tags', to='taggit.Tag', blank=True, through='taggit.TaggedItem', help_text=None)), + ('uploaded_by_user', models.ForeignKey(null=True, blank=True, to=settings.AUTH_USER_MODEL, editable=False)), + ], + options={ + 'abstract': False, + }, + bases=(models.Model, wagtail.wagtailadmin.taggable.TagSearchable), + ), + migrations.CreateModel( + name='CustomImageWithoutAdminFormFields', + fields=[ + ('id', models.AutoField(serialize=False, auto_created=True, verbose_name='ID', primary_key=True)), + ('title', models.CharField(max_length=255, verbose_name='Title')), + ('file', models.ImageField(width_field='width', height_field='height', upload_to=wagtail.wagtailimages.models.get_upload_to, verbose_name='File')), + ('width', models.IntegerField(editable=False)), + ('height', models.IntegerField(editable=False)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('focal_point_x', models.PositiveIntegerField(blank=True, null=True)), + ('focal_point_y', models.PositiveIntegerField(blank=True, null=True)), + ('focal_point_width', models.PositiveIntegerField(blank=True, null=True)), + ('focal_point_height', models.PositiveIntegerField(blank=True, null=True)), + ('caption', models.CharField(max_length=255)), + ('not_editable_field', models.CharField(max_length=255)), + ('tags', taggit.managers.TaggableManager(verbose_name='Tags', to='taggit.Tag', blank=True, through='taggit.TaggedItem', help_text=None)), + ('uploaded_by_user', models.ForeignKey(null=True, blank=True, to=settings.AUTH_USER_MODEL, editable=False)), + ], + options={ + 'abstract': False, + }, + bases=(models.Model, wagtail.wagtailadmin.taggable.TagSearchable), + ), + migrations.CreateModel( + name='EventIndex', + fields=[ + ('page_ptr', models.OneToOneField(parent_link=True, primary_key=True, to='wagtailcore.Page', auto_created=True, serialize=False)), + ('intro', wagtail.wagtailcore.fields.RichTextField(blank=True)), + ], + options={ + 'abstract': False, + }, + bases=('wagtailcore.page',), + ), + migrations.CreateModel( + name='EventPage', + fields=[ + ('page_ptr', models.OneToOneField(parent_link=True, primary_key=True, to='wagtailcore.Page', auto_created=True, serialize=False)), + ('date_from', models.DateField(verbose_name='Start date', null=True)), + ('date_to', models.DateField(blank=True, help_text='Not required if event is on a single day', verbose_name='End date', null=True)), + ('time_from', models.TimeField(blank=True, verbose_name='Start time', null=True)), + ('time_to', models.TimeField(blank=True, verbose_name='End time', null=True)), + ('audience', models.CharField(choices=[('public', 'Public'), ('private', 'Private')], max_length=255)), + ('location', models.CharField(max_length=255)), + ('body', wagtail.wagtailcore.fields.RichTextField(blank=True)), + ('cost', models.CharField(max_length=255)), + ('signup_link', models.URLField(blank=True)), + ('feed_image', models.ForeignKey(to='wagtailimages.Image', null=True, related_name='+', blank=True, on_delete=django.db.models.deletion.SET_NULL)), + ], + options={ + 'abstract': False, + }, + bases=('wagtailcore.page',), + ), + migrations.CreateModel( + name='EventPageCarouselItem', + fields=[ + ('id', models.AutoField(serialize=False, auto_created=True, verbose_name='ID', primary_key=True)), + ('sort_order', models.IntegerField(editable=False, null=True, blank=True)), + ('link_external', models.URLField(blank=True, verbose_name='External link')), + ('embed_url', models.URLField(blank=True, verbose_name='Embed URL')), + ('caption', models.CharField(blank=True, max_length=255)), + ('image', models.ForeignKey(to='wagtailimages.Image', null=True, related_name='+', blank=True, on_delete=django.db.models.deletion.SET_NULL)), + ('link_document', models.ForeignKey(to='wagtaildocs.Document', null=True, related_name='+', blank=True)), + ], + options={ + 'ordering': ['sort_order'], + 'abstract': False, + }, + bases=(models.Model,), + ), + migrations.CreateModel( + name='EventPageChooserModel', + fields=[ + ('id', models.AutoField(serialize=False, auto_created=True, verbose_name='ID', primary_key=True)), + ('page', models.ForeignKey(to='tests.EventPage', help_text='more help text')), + ], + options={ + }, + bases=(models.Model,), + ), + migrations.CreateModel( + name='EventPageRelatedLink', + fields=[ + ('id', models.AutoField(serialize=False, auto_created=True, verbose_name='ID', primary_key=True)), + ('sort_order', models.IntegerField(editable=False, null=True, blank=True)), + ('link_external', models.URLField(blank=True, verbose_name='External link')), + ('title', models.CharField(help_text='Link title', max_length=255)), + ('link_document', models.ForeignKey(to='wagtaildocs.Document', null=True, related_name='+', blank=True)), + ], + options={ + 'ordering': ['sort_order'], + 'abstract': False, + }, + bases=(models.Model,), + ), + migrations.CreateModel( + name='EventPageSpeaker', + fields=[ + ('id', models.AutoField(serialize=False, auto_created=True, verbose_name='ID', primary_key=True)), + ('sort_order', models.IntegerField(editable=False, null=True, blank=True)), + ('link_external', models.URLField(blank=True, verbose_name='External link')), + ('first_name', models.CharField(blank=True, max_length=255, verbose_name='Name')), + ('last_name', models.CharField(blank=True, max_length=255, verbose_name='Surname')), + ('image', models.ForeignKey(to='wagtailimages.Image', null=True, related_name='+', blank=True, on_delete=django.db.models.deletion.SET_NULL)), + ('link_document', models.ForeignKey(to='wagtaildocs.Document', null=True, related_name='+', blank=True)), + ], + options={ + 'ordering': ['sort_order'], + 'abstract': False, + }, + bases=(models.Model,), + ), + migrations.CreateModel( + name='FormField', + fields=[ + ('id', models.AutoField(serialize=False, auto_created=True, verbose_name='ID', primary_key=True)), + ('sort_order', models.IntegerField(editable=False, null=True, blank=True)), + ('label', models.CharField(help_text='The label of the form field', max_length=255)), + ('field_type', models.CharField(choices=[('singleline', 'Single line text'), ('multiline', 'Multi-line text'), ('email', 'Email'), ('number', 'Number'), ('url', 'URL'), ('checkbox', 'Checkbox'), ('checkboxes', 'Checkboxes'), ('dropdown', 'Drop down'), ('radio', 'Radio buttons'), ('date', 'Date'), ('datetime', 'Date/time')], max_length=16)), + ('required', models.BooleanField(default=True)), + ('choices', models.CharField(blank=True, help_text='Comma separated list of choices. Only applicable in checkboxes, radio and dropdown.', max_length=512)), + ('default_value', models.CharField(blank=True, help_text='Default value. Comma separated values supported for checkboxes.', max_length=255)), + ('help_text', models.CharField(blank=True, max_length=255)), + ], + options={ + 'ordering': ['sort_order'], + 'abstract': False, + }, + bases=(models.Model,), + ), + migrations.CreateModel( + name='FormPage', + fields=[ + ('page_ptr', models.OneToOneField(parent_link=True, primary_key=True, to='wagtailcore.Page', auto_created=True, serialize=False)), + ('to_address', models.CharField(blank=True, help_text='Optional - form submissions will be emailed to this address', max_length=255)), + ('from_address', models.CharField(blank=True, max_length=255)), + ('subject', models.CharField(blank=True, max_length=255)), + ], + options={ + 'abstract': False, + }, + bases=('wagtailcore.page',), + ), + migrations.CreateModel( + name='PageChooserModel', + fields=[ + ('id', models.AutoField(serialize=False, auto_created=True, verbose_name='ID', primary_key=True)), + ], + options={ + }, + bases=(models.Model,), + ), + migrations.CreateModel( + name='PageWithOldStyleRouteMethod', + fields=[ + ('page_ptr', models.OneToOneField(parent_link=True, primary_key=True, to='wagtailcore.Page', auto_created=True, serialize=False)), + ('content', models.TextField()), + ], + options={ + 'abstract': False, + }, + bases=('wagtailcore.page',), + ), + migrations.CreateModel( + name='SimplePage', + fields=[ + ('page_ptr', models.OneToOneField(parent_link=True, primary_key=True, to='wagtailcore.Page', auto_created=True, serialize=False)), + ('content', models.TextField()), + ], + options={ + 'abstract': False, + }, + bases=('wagtailcore.page',), + ), + migrations.CreateModel( + name='SnippetChooserModel', + fields=[ + ('id', models.AutoField(serialize=False, auto_created=True, verbose_name='ID', primary_key=True)), + ('advert', models.ForeignKey(to='tests.Advert', help_text='help text')), + ], + options={ + }, + bases=(models.Model,), + ), + migrations.CreateModel( + name='StandardChild', + fields=[ + ('page_ptr', models.OneToOneField(parent_link=True, primary_key=True, to='wagtailcore.Page', auto_created=True, serialize=False)), + ], + options={ + 'abstract': False, + }, + bases=('wagtailcore.page',), + ), + migrations.CreateModel( + name='StandardIndex', + fields=[ + ('page_ptr', models.OneToOneField(parent_link=True, primary_key=True, to='wagtailcore.Page', auto_created=True, serialize=False)), + ], + options={ + 'abstract': False, + }, + bases=('wagtailcore.page',), + ), + migrations.CreateModel( + name='TaggedPage', + fields=[ + ('page_ptr', models.OneToOneField(parent_link=True, primary_key=True, to='wagtailcore.Page', auto_created=True, serialize=False)), + ], + options={ + 'abstract': False, + }, + bases=('wagtailcore.page',), + ), + migrations.CreateModel( + name='TaggedPageTag', + fields=[ + ('id', models.AutoField(serialize=False, auto_created=True, verbose_name='ID', primary_key=True)), + ('content_object', modelcluster.fields.ParentalKey(to='tests.TaggedPage', related_name='tagged_items')), + ('tag', models.ForeignKey(to='taggit.Tag', related_name='tests_taggedpagetag_items')), ], options={ 'abstract': False, }, bases=(models.Model,), ), + migrations.AddField( + model_name='taggedpage', + name='tags', + field=modelcluster.tags.ClusterTaggableManager(verbose_name='Tags', to='taggit.Tag', blank=True, through='tests.TaggedPageTag', help_text='A comma-separated list of tags.'), + preserve_default=True, + ), + migrations.AddField( + model_name='pagechoosermodel', + name='page', + field=models.ForeignKey(to='wagtailcore.Page', help_text='help text'), + preserve_default=True, + ), + migrations.AddField( + model_name='formfield', + name='page', + field=modelcluster.fields.ParentalKey(to='tests.FormPage', related_name='form_fields'), + preserve_default=True, + ), + migrations.AddField( + model_name='eventpagespeaker', + name='link_page', + field=models.ForeignKey(to='wagtailcore.Page', null=True, related_name='+', blank=True), + preserve_default=True, + ), + migrations.AddField( + model_name='eventpagespeaker', + name='page', + field=modelcluster.fields.ParentalKey(to='tests.EventPage', related_name='speakers'), + preserve_default=True, + ), + migrations.AddField( + model_name='eventpagerelatedlink', + name='link_page', + field=models.ForeignKey(to='wagtailcore.Page', null=True, related_name='+', blank=True), + preserve_default=True, + ), + migrations.AddField( + model_name='eventpagerelatedlink', + name='page', + field=modelcluster.fields.ParentalKey(to='tests.EventPage', related_name='related_links'), + preserve_default=True, + ), + migrations.AddField( + model_name='eventpagecarouselitem', + name='link_page', + field=models.ForeignKey(to='wagtailcore.Page', null=True, related_name='+', blank=True), + preserve_default=True, + ), + migrations.AddField( + model_name='eventpagecarouselitem', + name='page', + field=modelcluster.fields.ParentalKey(to='tests.EventPage', related_name='carousel_items'), + preserve_default=True, + ), + migrations.AddField( + model_name='advertplacement', + name='page', + field=modelcluster.fields.ParentalKey(to='wagtailcore.Page', related_name='advert_placements'), + preserve_default=True, + ), ] diff --git a/wagtail/tests/testapp/migrations/0002_auto_20140827_0908.py b/wagtail/tests/testapp/migrations/0002_auto_20140827_0908.py deleted file mode 100644 index 66c85ffb0..000000000 --- a/wagtail/tests/testapp/migrations/0002_auto_20140827_0908.py +++ /dev/null @@ -1,386 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import models, migrations -import django.db.models.deletion -import modelcluster.fields -import wagtail.contrib.wagtailroutablepage.models -import wagtail.wagtailcore.fields -import wagtail.wagtailsearch.index -import modelcluster.tags - - -class Migration(migrations.Migration): - - dependencies = [ - ('wagtailcore', '0002_initial_data'), - ('wagtaildocs', '0002_initial_data'), - ('taggit', '0001_initial'), - ('wagtailimages', '0002_initial_data'), - ('tests', '0001_initial'), - ] - - operations = [ - migrations.CreateModel( - name='Advert', - fields=[ - ('id', models.AutoField(auto_created=True, verbose_name='ID', primary_key=True, serialize=False)), - ('url', models.URLField(null=True, blank=True)), - ('text', models.CharField(max_length=255)), - ], - options={ - }, - bases=(models.Model,), - ), - migrations.CreateModel( - name='AdvertPlacement', - fields=[ - ('id', models.AutoField(auto_created=True, verbose_name='ID', primary_key=True, serialize=False)), - ('advert', models.ForeignKey(to='tests.Advert', related_name='+')), - ], - options={ - }, - bases=(models.Model,), - ), - migrations.CreateModel( - name='AlphaSnippet', - fields=[ - ('id', models.AutoField(auto_created=True, verbose_name='ID', primary_key=True, serialize=False)), - ('text', models.CharField(max_length=255)), - ], - options={ - }, - bases=(models.Model,), - ), - migrations.CreateModel( - name='BusinessChild', - fields=[ - ('page_ptr', models.OneToOneField(parent_link=True, to='wagtailcore.Page', serialize=False, auto_created=True, primary_key=True)), - ], - options={ - 'abstract': False, - }, - bases=('wagtailcore.page',), - ), - migrations.CreateModel( - name='BusinessIndex', - fields=[ - ('page_ptr', models.OneToOneField(parent_link=True, to='wagtailcore.Page', serialize=False, auto_created=True, primary_key=True)), - ], - options={ - 'abstract': False, - }, - bases=('wagtailcore.page',), - ), - migrations.CreateModel( - name='BusinessSubIndex', - fields=[ - ('page_ptr', models.OneToOneField(parent_link=True, to='wagtailcore.Page', serialize=False, auto_created=True, primary_key=True)), - ], - options={ - 'abstract': False, - }, - bases=('wagtailcore.page',), - ), - migrations.CreateModel( - name='EventIndex', - fields=[ - ('page_ptr', models.OneToOneField(parent_link=True, to='wagtailcore.Page', serialize=False, auto_created=True, primary_key=True)), - ('intro', wagtail.wagtailcore.fields.RichTextField(blank=True)), - ], - options={ - 'abstract': False, - }, - bases=('wagtailcore.page',), - ), - migrations.CreateModel( - name='EventPage', - fields=[ - ('page_ptr', models.OneToOneField(parent_link=True, to='wagtailcore.Page', serialize=False, auto_created=True, primary_key=True)), - ('date_from', models.DateField(null=True, verbose_name='Start date')), - ('date_to', models.DateField(null=True, help_text='Not required if event is on a single day', blank=True, verbose_name='End date')), - ('time_from', models.TimeField(null=True, blank=True, verbose_name='Start time')), - ('time_to', models.TimeField(null=True, blank=True, verbose_name='End time')), - ('audience', models.CharField(choices=[('public', 'Public'), ('private', 'Private')], max_length=255)), - ('location', models.CharField(max_length=255)), - ('body', wagtail.wagtailcore.fields.RichTextField(blank=True)), - ('cost', models.CharField(max_length=255)), - ('signup_link', models.URLField(blank=True)), - ('feed_image', models.ForeignKey(related_name='+', blank=True, to='wagtailimages.Image', on_delete=django.db.models.deletion.SET_NULL, null=True)), - ], - options={ - 'abstract': False, - }, - bases=('wagtailcore.page',), - ), - migrations.CreateModel( - name='EventPageCarouselItem', - fields=[ - ('id', models.AutoField(auto_created=True, verbose_name='ID', primary_key=True, serialize=False)), - ('sort_order', models.IntegerField(null=True, blank=True, editable=False)), - ('link_external', models.URLField(blank=True, verbose_name='External link')), - ('embed_url', models.URLField(blank=True, verbose_name='Embed URL')), - ('caption', models.CharField(blank=True, max_length=255)), - ('image', models.ForeignKey(related_name='+', blank=True, to='wagtailimages.Image', on_delete=django.db.models.deletion.SET_NULL, null=True)), - ('link_document', models.ForeignKey(related_name='+', blank=True, to='wagtaildocs.Document', null=True)), - ], - options={ - 'abstract': False, - 'ordering': ['sort_order'], - }, - bases=(models.Model,), - ), - migrations.CreateModel( - name='EventPageRelatedLink', - fields=[ - ('id', models.AutoField(auto_created=True, verbose_name='ID', primary_key=True, serialize=False)), - ('sort_order', models.IntegerField(null=True, blank=True, editable=False)), - ('link_external', models.URLField(blank=True, verbose_name='External link')), - ('title', models.CharField(help_text='Link title', max_length=255)), - ('link_document', models.ForeignKey(related_name='+', blank=True, to='wagtaildocs.Document', null=True)), - ], - options={ - 'abstract': False, - 'ordering': ['sort_order'], - }, - bases=(models.Model,), - ), - migrations.CreateModel( - name='EventPageSpeaker', - fields=[ - ('id', models.AutoField(auto_created=True, verbose_name='ID', primary_key=True, serialize=False)), - ('sort_order', models.IntegerField(null=True, blank=True, editable=False)), - ('link_external', models.URLField(blank=True, verbose_name='External link')), - ('first_name', models.CharField(blank=True, verbose_name='Name', max_length=255)), - ('last_name', models.CharField(blank=True, verbose_name='Surname', max_length=255)), - ('image', models.ForeignKey(related_name='+', blank=True, to='wagtailimages.Image', on_delete=django.db.models.deletion.SET_NULL, null=True)), - ('link_document', models.ForeignKey(related_name='+', blank=True, to='wagtaildocs.Document', null=True)), - ], - options={ - 'abstract': False, - 'ordering': ['sort_order'], - }, - bases=(models.Model,), - ), - migrations.CreateModel( - name='FormField', - fields=[ - ('id', models.AutoField(auto_created=True, verbose_name='ID', primary_key=True, serialize=False)), - ('sort_order', models.IntegerField(null=True, blank=True, editable=False)), - ('label', models.CharField(help_text='The label of the form field', max_length=255)), - ('field_type', models.CharField(choices=[('singleline', 'Single line text'), ('multiline', 'Multi-line text'), ('email', 'Email'), ('number', 'Number'), ('url', 'URL'), ('checkbox', 'Checkbox'), ('checkboxes', 'Checkboxes'), ('dropdown', 'Drop down'), ('radio', 'Radio buttons'), ('date', 'Date'), ('datetime', 'Date/time')], max_length=16)), - ('required', models.BooleanField(default=True)), - ('choices', models.CharField(blank=True, help_text='Comma seperated list of choices. Only applicable in checkboxes, radio and dropdown.', max_length=512)), - ('default_value', models.CharField(blank=True, help_text='Default value. Comma seperated values supported for checkboxes.', max_length=255)), - ('help_text', models.CharField(blank=True, max_length=255)), - ], - options={ - 'abstract': False, - 'ordering': ['sort_order'], - }, - bases=(models.Model,), - ), - migrations.CreateModel( - name='FormPage', - fields=[ - ('page_ptr', models.OneToOneField(parent_link=True, to='wagtailcore.Page', serialize=False, auto_created=True, primary_key=True)), - ('to_address', models.CharField(blank=True, help_text='Optional - form submissions will be emailed to this address', max_length=255)), - ('from_address', models.CharField(blank=True, max_length=255)), - ('subject', models.CharField(blank=True, max_length=255)), - ], - options={ - 'abstract': False, - }, - bases=('wagtailcore.page',), - ), - migrations.CreateModel( - name='PageWithOldStyleRouteMethod', - fields=[ - ('page_ptr', models.OneToOneField(parent_link=True, to='wagtailcore.Page', serialize=False, auto_created=True, primary_key=True)), - ('content', models.TextField()), - ], - options={ - 'abstract': False, - }, - bases=('wagtailcore.page',), - ), - migrations.CreateModel( - name='RoutablePageTest', - fields=[ - ('page_ptr', models.OneToOneField(parent_link=True, to='wagtailcore.Page', serialize=False, auto_created=True, primary_key=True)), - ], - options={ - 'abstract': False, - }, - bases=(wagtail.contrib.wagtailroutablepage.models.RoutablePageMixin, 'wagtailcore.page'), - ), - migrations.CreateModel( - name='SearchTest', - fields=[ - ('id', models.AutoField(auto_created=True, verbose_name='ID', primary_key=True, serialize=False)), - ('title', models.CharField(max_length=255)), - ('content', models.TextField()), - ('live', models.BooleanField(default=False)), - ('published_date', models.DateField(null=True)), - ], - options={ - }, - bases=(models.Model, wagtail.wagtailsearch.index.Indexed), - ), - migrations.CreateModel( - name='SearchTestChild', - fields=[ - ('searchtest_ptr', models.OneToOneField(parent_link=True, to='tests.SearchTest', serialize=False, auto_created=True, primary_key=True)), - ('subtitle', models.CharField(null=True, blank=True, max_length=255)), - ('extra_content', models.TextField()), - ], - options={ - }, - bases=('tests.searchtest',), - ), - migrations.CreateModel( - name='SearchTestOldConfig', - fields=[ - ('id', models.AutoField(auto_created=True, verbose_name='ID', primary_key=True, serialize=False)), - ], - options={ - }, - bases=(models.Model, wagtail.wagtailsearch.index.Indexed), - ), - migrations.CreateModel( - name='SearchTestOldConfigList', - fields=[ - ('id', models.AutoField(auto_created=True, verbose_name='ID', primary_key=True, serialize=False)), - ], - options={ - }, - bases=(models.Model, wagtail.wagtailsearch.index.Indexed), - ), - migrations.CreateModel( - name='SimplePage', - fields=[ - ('page_ptr', models.OneToOneField(parent_link=True, to='wagtailcore.Page', serialize=False, auto_created=True, primary_key=True)), - ('content', models.TextField()), - ], - options={ - 'abstract': False, - }, - bases=('wagtailcore.page',), - ), - migrations.CreateModel( - name='StandardChild', - fields=[ - ('page_ptr', models.OneToOneField(parent_link=True, to='wagtailcore.Page', serialize=False, auto_created=True, primary_key=True)), - ], - options={ - 'abstract': False, - }, - bases=('wagtailcore.page',), - ), - migrations.CreateModel( - name='StandardIndex', - fields=[ - ('page_ptr', models.OneToOneField(parent_link=True, to='wagtailcore.Page', serialize=False, auto_created=True, primary_key=True)), - ], - options={ - 'abstract': False, - }, - bases=('wagtailcore.page',), - ), - migrations.CreateModel( - name='TaggedPage', - fields=[ - ('page_ptr', models.OneToOneField(parent_link=True, to='wagtailcore.Page', serialize=False, auto_created=True, primary_key=True)), - ], - options={ - 'abstract': False, - }, - bases=('wagtailcore.page',), - ), - migrations.CreateModel( - name='TaggedPageTag', - fields=[ - ('id', models.AutoField(auto_created=True, verbose_name='ID', primary_key=True, serialize=False)), - ('content_object', modelcluster.fields.ParentalKey(to='tests.TaggedPage', related_name='tagged_items')), - ('tag', models.ForeignKey(to='taggit.Tag', related_name='tests_taggedpagetag_items')), - ], - options={ - 'abstract': False, - }, - bases=(models.Model,), - ), - migrations.CreateModel( - name='ZuluSnippet', - fields=[ - ('id', models.AutoField(auto_created=True, verbose_name='ID', primary_key=True, serialize=False)), - ('text', models.CharField(max_length=255)), - ], - options={ - }, - bases=(models.Model,), - ), - migrations.AddField( - model_name='taggedpage', - name='tags', - field=modelcluster.tags.ClusterTaggableManager(through='tests.TaggedPageTag', blank=True, verbose_name='Tags', to='taggit.Tag', help_text='A comma-separated list of tags.'), - preserve_default=True, - ), - migrations.AddField( - model_name='formfield', - name='page', - field=modelcluster.fields.ParentalKey(to='tests.FormPage', related_name='form_fields'), - preserve_default=True, - ), - migrations.AddField( - model_name='eventpagespeaker', - name='link_page', - field=models.ForeignKey(related_name='+', blank=True, to='wagtailcore.Page', null=True), - preserve_default=True, - ), - migrations.AddField( - model_name='eventpagespeaker', - name='page', - field=modelcluster.fields.ParentalKey(to='tests.EventPage', related_name='speakers'), - preserve_default=True, - ), - migrations.AddField( - model_name='eventpagerelatedlink', - name='link_page', - field=models.ForeignKey(related_name='+', blank=True, to='wagtailcore.Page', null=True), - preserve_default=True, - ), - migrations.AddField( - model_name='eventpagerelatedlink', - name='page', - field=modelcluster.fields.ParentalKey(to='tests.EventPage', related_name='related_links'), - preserve_default=True, - ), - migrations.AddField( - model_name='eventpagecarouselitem', - name='link_page', - field=models.ForeignKey(related_name='+', blank=True, to='wagtailcore.Page', null=True), - preserve_default=True, - ), - migrations.AddField( - model_name='eventpagecarouselitem', - name='page', - field=modelcluster.fields.ParentalKey(to='tests.EventPage', related_name='carousel_items'), - preserve_default=True, - ), - migrations.AddField( - model_name='advertplacement', - name='page', - field=modelcluster.fields.ParentalKey(to='wagtailcore.Page', related_name='advert_placements'), - preserve_default=True, - ), - migrations.AlterField( - model_name='customuser', - name='groups', - field=models.ManyToManyField(related_name='user_set', blank=True, verbose_name='groups', to='auth.Group', related_query_name='user', help_text='The groups this user belongs to. A user will get all permissions granted to each of his/her group.'), - ), - migrations.AlterField( - model_name='customuser', - name='user_permissions', - field=models.ManyToManyField(related_name='user_set', blank=True, verbose_name='user permissions', to='auth.Permission', related_query_name='user', help_text='Specific permissions for this user.'), - ), - ] diff --git a/wagtail/tests/testapp/migrations/0003_auto_20140905_0634.py b/wagtail/tests/testapp/migrations/0003_auto_20140905_0634.py deleted file mode 100644 index c1f69f529..000000000 --- a/wagtail/tests/testapp/migrations/0003_auto_20140905_0634.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import models, migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('tests', '0002_auto_20140827_0908'), - ] - - operations = [ - migrations.AddField( - model_name='advertplacement', - name='colour', - field=models.CharField(default='blue', max_length=255), - preserve_default=False, - ), - ] diff --git a/wagtail/tests/testapp/migrations/0004_auto_20141008_0420.py b/wagtail/tests/testapp/migrations/0004_auto_20141008_0420.py deleted file mode 100644 index d5002a776..000000000 --- a/wagtail/tests/testapp/migrations/0004_auto_20141008_0420.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import models, migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('tests', '0003_auto_20140905_0634'), - ] - - operations = [ - migrations.DeleteModel( - name='SearchTestOldConfig', - ), - migrations.DeleteModel( - name='SearchTestOldConfigList', - ), - ] diff --git a/wagtail/tests/testapp/migrations/0005_auto_20141008_0122.py b/wagtail/tests/testapp/migrations/0005_auto_20141008_0122.py deleted file mode 100644 index 801e1f5df..000000000 --- a/wagtail/tests/testapp/migrations/0005_auto_20141008_0122.py +++ /dev/null @@ -1,35 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import models, migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('wagtailcore', '0002_initial_data'), - ('tests', '0004_auto_20141008_0420'), - ] - - operations = [ - migrations.CreateModel( - name='PageChooserModel', - fields=[ - ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('page', models.ForeignKey(help_text=b'help text', to='wagtailcore.Page')), - ], - options={ - }, - bases=(models.Model,), - ), - migrations.CreateModel( - name='SnippetChooserModel', - fields=[ - ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('advert', models.ForeignKey(help_text=b'help text', to='tests.Advert')), - ], - options={ - }, - bases=(models.Model,), - ), - ] diff --git a/wagtail/tests/testapp/migrations/0005_auto_20141113_0642.py b/wagtail/tests/testapp/migrations/0005_auto_20141113_0642.py deleted file mode 100644 index 37f5744c8..000000000 --- a/wagtail/tests/testapp/migrations/0005_auto_20141113_0642.py +++ /dev/null @@ -1,27 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import models, migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('wagtailcore', '0002_initial_data'), - ('tests', '0004_auto_20141008_0420'), - ] - - operations = [ - migrations.AlterField( - model_name='formfield', - name='choices', - field=models.CharField(help_text='Comma separated list of choices. Only applicable in checkboxes, radio and dropdown.', max_length=512, blank=True), - preserve_default=True, - ), - migrations.AlterField( - model_name='formfield', - name='default_value', - field=models.CharField(help_text='Default value. Comma separated values supported for checkboxes.', max_length=255, blank=True), - preserve_default=True, - ), - ] diff --git a/wagtail/tests/testapp/migrations/0006_merge.py b/wagtail/tests/testapp/migrations/0006_merge.py deleted file mode 100644 index 7489198a7..000000000 --- a/wagtail/tests/testapp/migrations/0006_merge.py +++ /dev/null @@ -1,15 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import models, migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('tests', '0005_auto_20141113_0642'), - ('tests', '0005_auto_20141008_0122'), - ] - - operations = [ - ] diff --git a/wagtail/tests/testapp/migrations/0007_auto_20141118_0925.py b/wagtail/tests/testapp/migrations/0007_auto_20141118_0925.py deleted file mode 100644 index be6775130..000000000 --- a/wagtail/tests/testapp/migrations/0007_auto_20141118_0925.py +++ /dev/null @@ -1,26 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import models, migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('tests', '0006_merge'), - ] - - operations = [ - migrations.AlterField( - model_name='pagechoosermodel', - name='page', - field=models.ForeignKey(to='wagtailcore.Page', help_text='help text'), - preserve_default=True, - ), - migrations.AlterField( - model_name='snippetchoosermodel', - name='advert', - field=models.ForeignKey(to='tests.Advert', help_text='help text'), - preserve_default=True, - ), - ] diff --git a/wagtail/tests/testapp/migrations/0008_registerdecorator.py b/wagtail/tests/testapp/migrations/0008_registerdecorator.py deleted file mode 100644 index c82debdf8..000000000 --- a/wagtail/tests/testapp/migrations/0008_registerdecorator.py +++ /dev/null @@ -1,32 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import models, migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('tests', '0007_auto_20141118_0925'), - ] - - operations = [ - migrations.CreateModel( - name='RegisterDecorator', - fields=[ - ('id', models.AutoField(serialize=False, auto_created=True, verbose_name='ID', primary_key=True)), - ], - options={ - }, - bases=(models.Model,), - ), - migrations.CreateModel( - name='RegisterFunction', - fields=[ - ('id', models.AutoField(serialize=False, auto_created=True, verbose_name='ID', primary_key=True)), - ], - options={ - }, - bases=(models.Model,), - ), - ] diff --git a/wagtail/tests/testapp/migrations/0009_eventpagechoosermodel.py b/wagtail/tests/testapp/migrations/0009_eventpagechoosermodel.py deleted file mode 100644 index 6b6e505d7..000000000 --- a/wagtail/tests/testapp/migrations/0009_eventpagechoosermodel.py +++ /dev/null @@ -1,24 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import models, migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('tests', '0008_registerdecorator'), - ] - - operations = [ - migrations.CreateModel( - name='EventPageChooserModel', - fields=[ - ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('page', models.ForeignKey(help_text='more help text', to='tests.EventPage')), - ], - options={ - }, - bases=(models.Model,), - ), - ] diff --git a/wagtail/tests/testapp/migrations/0010_customimagewithadminformfields_customimagewithoutadminformfields.py b/wagtail/tests/testapp/migrations/0010_customimagewithadminformfields_customimagewithoutadminformfields.py deleted file mode 100644 index 1b7f7c9b9..000000000 --- a/wagtail/tests/testapp/migrations/0010_customimagewithadminformfields_customimagewithoutadminformfields.py +++ /dev/null @@ -1,65 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import models, migrations -import wagtail.wagtailadmin.taggable -from django.conf import settings -import taggit.managers -import wagtail.wagtailimages.models - - -class Migration(migrations.Migration): - - dependencies = [ - ('taggit', '0001_initial'), - ('tests', '0009_eventpagechoosermodel'), - ] - - operations = [ - migrations.CreateModel( - name='CustomImageWithAdminFormFields', - fields=[ - ('id', models.AutoField(serialize=False, verbose_name='ID', auto_created=True, primary_key=True)), - ('title', models.CharField(verbose_name='Title', max_length=255)), - ('file', models.ImageField(verbose_name='File', height_field='height', upload_to=wagtail.wagtailimages.models.get_upload_to, width_field='width')), - ('width', models.IntegerField(editable=False)), - ('height', models.IntegerField(editable=False)), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('focal_point_x', models.PositiveIntegerField(blank=True, null=True)), - ('focal_point_y', models.PositiveIntegerField(blank=True, null=True)), - ('focal_point_width', models.PositiveIntegerField(blank=True, null=True)), - ('focal_point_height', models.PositiveIntegerField(blank=True, null=True)), - ('caption', models.CharField(max_length=255)), - ('not_editable_field', models.CharField(max_length=255)), - ('tags', taggit.managers.TaggableManager(verbose_name='Tags', help_text=None, through='taggit.TaggedItem', blank=True, to='taggit.Tag')), - ('uploaded_by_user', models.ForeignKey(to=settings.AUTH_USER_MODEL, null=True, blank=True, editable=False)), - ], - options={ - 'abstract': False, - }, - bases=(models.Model, wagtail.wagtailadmin.taggable.TagSearchable), - ), - migrations.CreateModel( - name='CustomImageWithoutAdminFormFields', - fields=[ - ('id', models.AutoField(serialize=False, verbose_name='ID', auto_created=True, primary_key=True)), - ('title', models.CharField(verbose_name='Title', max_length=255)), - ('file', models.ImageField(verbose_name='File', height_field='height', upload_to=wagtail.wagtailimages.models.get_upload_to, width_field='width')), - ('width', models.IntegerField(editable=False)), - ('height', models.IntegerField(editable=False)), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('focal_point_x', models.PositiveIntegerField(blank=True, null=True)), - ('focal_point_y', models.PositiveIntegerField(blank=True, null=True)), - ('focal_point_width', models.PositiveIntegerField(blank=True, null=True)), - ('focal_point_height', models.PositiveIntegerField(blank=True, null=True)), - ('caption', models.CharField(max_length=255)), - ('not_editable_field', models.CharField(max_length=255)), - ('tags', taggit.managers.TaggableManager(verbose_name='Tags', help_text=None, through='taggit.TaggedItem', blank=True, to='taggit.Tag')), - ('uploaded_by_user', models.ForeignKey(to=settings.AUTH_USER_MODEL, null=True, blank=True, editable=False)), - ], - options={ - 'abstract': False, - }, - bases=(models.Model, wagtail.wagtailadmin.taggable.TagSearchable), - ), - ] diff --git a/wagtail/tests/testapp/migrations/0011_auto_20150330_0653.py b/wagtail/tests/testapp/migrations/0011_auto_20150330_0653.py deleted file mode 100644 index 0bc4febdc..000000000 --- a/wagtail/tests/testapp/migrations/0011_auto_20150330_0653.py +++ /dev/null @@ -1,25 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import models, migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('tests', '0010_customimagewithadminformfields_customimagewithoutadminformfields'), - ] - - operations = [ - migrations.RemoveField( - model_name='customuser', - name='groups', - ), - migrations.RemoveField( - model_name='customuser', - name='user_permissions', - ), - migrations.DeleteModel( - name='CustomUser', - ), - ] diff --git a/wagtail/tests/testapp/migrations/0012_auto_20150330_0709.py b/wagtail/tests/testapp/migrations/0012_auto_20150330_0709.py deleted file mode 100644 index 79e0d1553..000000000 --- a/wagtail/tests/testapp/migrations/0012_auto_20150330_0709.py +++ /dev/null @@ -1,26 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import models, migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('tests', '0011_auto_20150330_0653'), - ] - - operations = [ - migrations.DeleteModel( - name='AlphaSnippet', - ), - migrations.DeleteModel( - name='RegisterDecorator', - ), - migrations.DeleteModel( - name='RegisterFunction', - ), - migrations.DeleteModel( - name='ZuluSnippet', - ), - ] diff --git a/wagtail/tests/testapp/migrations/0013_auto_20150330_0717.py b/wagtail/tests/testapp/migrations/0013_auto_20150330_0717.py deleted file mode 100644 index 8f27b4439..000000000 --- a/wagtail/tests/testapp/migrations/0013_auto_20150330_0717.py +++ /dev/null @@ -1,21 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import models, migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('wagtailcore', '0013_update_golive_expire_help_text'), - ('wagtailforms', '0001_initial'), - ('wagtailredirects', '0001_initial'), - ('wagtailsearch', '0001_initial'), - ('tests', '0012_auto_20150330_0709'), - ] - - operations = [ - migrations.DeleteModel( - name='RoutablePageTest', - ), - ] diff --git a/wagtail/tests/testapp/migrations/0014_auto_20150330_0728.py b/wagtail/tests/testapp/migrations/0014_auto_20150330_0728.py deleted file mode 100644 index 3217ac402..000000000 --- a/wagtail/tests/testapp/migrations/0014_auto_20150330_0728.py +++ /dev/null @@ -1,24 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import models, migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('tests', '0013_auto_20150330_0717'), - ] - - operations = [ - migrations.RemoveField( - model_name='searchtestchild', - name='searchtest_ptr', - ), - migrations.DeleteModel( - name='SearchTestChild', - ), - migrations.DeleteModel( - name='SearchTest', - ), - ] From 2c50926785d0b54e19ca87f7e3f9969a650b3e8d Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Mon, 30 Mar 2015 14:41:41 +0100 Subject: [PATCH 07/27] No longer use celery for sending notifications --- wagtail/wagtailadmin/tasks.py | 101 ---------------------------- wagtail/wagtailadmin/tests/tests.py | 2 +- wagtail/wagtailadmin/utils.py | 79 +++++++++++++++++++++- wagtail/wagtailadmin/views/pages.py | 11 +-- wagtail/wagtailforms/models.py | 4 +- 5 files changed, 87 insertions(+), 110 deletions(-) delete mode 100644 wagtail/wagtailadmin/tasks.py diff --git a/wagtail/wagtailadmin/tasks.py b/wagtail/wagtailadmin/tasks.py deleted file mode 100644 index 815971e46..000000000 --- a/wagtail/wagtailadmin/tasks.py +++ /dev/null @@ -1,101 +0,0 @@ -from django.template.loader import render_to_string -from django.core.mail import send_mail -from django.conf import settings -from django.contrib.auth import get_user_model -from django.db.models import Q - -from wagtail.wagtailcore.models import PageRevision, GroupPagePermission -from wagtail.wagtailusers.models import UserProfile - -# The following will check to see if we can import task from celery - -# if not then we definitely haven't installed it -try: - from celery.decorators import task - NO_CELERY = False -except: - NO_CELERY = True - - -# However, we could have installed celery for other projects. So we will also -# check if we have defined the BROKER_URL setting. If not then definitely we -# haven't configured it. -if NO_CELERY or not hasattr(settings, 'BROKER_URL'): - # So if we enter here we will define a different "task" decorator that - # just returns the original function and sets its delay attribute to - # point to the original function: This way, the send_notification - # function will be actually called instead of the the - # send_notification.delay() - def task(f): - f.delay=f - return f - -def users_with_page_permission(page, permission_type, include_superusers=True): - # Get user model - User = get_user_model() - - # Find GroupPagePermission records of the given type that apply to this page or an ancestor - ancestors_and_self = list(page.get_ancestors()) + [page] - perm = GroupPagePermission.objects.filter(permission_type=permission_type, page__in=ancestors_and_self) - q = Q(groups__page_permissions=perm) - - # Include superusers - if include_superusers: - q |= Q(is_superuser=True) - - return User.objects.filter(is_active=True).filter(q).distinct() - - -@task -def send_notification(page_revision_id, notification, excluded_user_id): - # Get revision - revision = PageRevision.objects.get(id=page_revision_id) - - # Get list of recipients - if notification == 'submitted': - # Get list of publishers - recipients = users_with_page_permission(revision.page, 'publish') - elif notification in ['rejected', 'approved']: - # Get submitter - recipients = [revision.user] - else: - return - - # Get list of email addresses - email_addresses = [ - recipient.email for recipient in recipients - if recipient.email and recipient.id != excluded_user_id and getattr(UserProfile.get_for_user(recipient), notification + '_notifications') - ] - - # Return if there are no email addresses - if not email_addresses: - return - - # Get email subject and content - template = 'wagtailadmin/notifications/' + notification + '.html' - rendered_template = render_to_string(template, dict(revision=revision, settings=settings)).split('\n') - email_subject = rendered_template[0] - email_content = '\n'.join(rendered_template[1:]) - - # Get from email - if hasattr(settings, 'WAGTAILADMIN_NOTIFICATION_FROM_EMAIL'): - from_email = settings.WAGTAILADMIN_NOTIFICATION_FROM_EMAIL - elif hasattr(settings, 'DEFAULT_FROM_EMAIL'): - from_email = settings.DEFAULT_FROM_EMAIL - else: - from_email = 'webmaster@localhost' - - # Send email - send_mail(email_subject, email_content, from_email, email_addresses) - - -@task -def send_email_task(email_subject, email_content, email_addresses, from_email=None): - if not from_email: - if hasattr(settings, 'WAGTAILADMIN_NOTIFICATION_FROM_EMAIL'): - from_email = settings.WAGTAILADMIN_NOTIFICATION_FROM_EMAIL - elif hasattr(settings, 'DEFAULT_FROM_EMAIL'): - from_email = settings.DEFAULT_FROM_EMAIL - else: - from_email = 'webmaster@localhost' - - send_mail(email_subject, email_content, from_email, email_addresses) diff --git a/wagtail/wagtailadmin/tests/tests.py b/wagtail/wagtailadmin/tests/tests.py index 834c20de5..2adebbfcf 100644 --- a/wagtail/wagtailadmin/tests/tests.py +++ b/wagtail/wagtailadmin/tests/tests.py @@ -4,7 +4,7 @@ from django.core import mail from wagtail.tests.utils import WagtailTestUtils from wagtail.wagtailcore.models import Page -from wagtail.wagtailadmin.tasks import send_email_task +from wagtail.wagtailadmin.utils import send_email_task class TestHome(TestCase, WagtailTestUtils): diff --git a/wagtail/wagtailadmin/utils.py b/wagtail/wagtailadmin/utils.py index 043b8336d..d864507d9 100644 --- a/wagtail/wagtailadmin/utils.py +++ b/wagtail/wagtailadmin/utils.py @@ -1,6 +1,13 @@ +from django.template.loader import render_to_string +from django.core.mail import send_mail +from django.conf import settings +from django.contrib.auth import get_user_model +from django.db.models import Q + from modelcluster.fields import ParentalKey -from wagtail.wagtailcore.models import Page +from wagtail.wagtailcore.models import Page, PageRevision, GroupPagePermission +from wagtail.wagtailusers.models import UserProfile def get_object_usage(obj): @@ -34,3 +41,73 @@ def get_object_usage(obj): ) return pages + + +def users_with_page_permission(page, permission_type, include_superusers=True): + # Get user model + User = get_user_model() + + # Find GroupPagePermission records of the given type that apply to this page or an ancestor + ancestors_and_self = list(page.get_ancestors()) + [page] + perm = GroupPagePermission.objects.filter(permission_type=permission_type, page__in=ancestors_and_self) + q = Q(groups__page_permissions=perm) + + # Include superusers + if include_superusers: + q |= Q(is_superuser=True) + + return User.objects.filter(is_active=True).filter(q).distinct() + + +def send_notification(page_revision_id, notification, excluded_user_id): + # Get revision + revision = PageRevision.objects.get(id=page_revision_id) + + # Get list of recipients + if notification == 'submitted': + # Get list of publishers + recipients = users_with_page_permission(revision.page, 'publish') + elif notification in ['rejected', 'approved']: + # Get submitter + recipients = [revision.user] + else: + return + + # Get list of email addresses + email_addresses = [ + recipient.email for recipient in recipients + if recipient.email and recipient.id != excluded_user_id and getattr(UserProfile.get_for_user(recipient), notification + '_notifications') + ] + + # Return if there are no email addresses + if not email_addresses: + return + + # Get email subject and content + template = 'wagtailadmin/notifications/' + notification + '.html' + rendered_template = render_to_string(template, dict(revision=revision, settings=settings)).split('\n') + email_subject = rendered_template[0] + email_content = '\n'.join(rendered_template[1:]) + + # Get from email + if hasattr(settings, 'WAGTAILADMIN_NOTIFICATION_FROM_EMAIL'): + from_email = settings.WAGTAILADMIN_NOTIFICATION_FROM_EMAIL + elif hasattr(settings, 'DEFAULT_FROM_EMAIL'): + from_email = settings.DEFAULT_FROM_EMAIL + else: + from_email = 'webmaster@localhost' + + # Send email + send_mail(email_subject, email_content, from_email, email_addresses) + + +def send_email_task(email_subject, email_content, email_addresses, from_email=None): + if not from_email: + if hasattr(settings, 'WAGTAILADMIN_NOTIFICATION_FROM_EMAIL'): + from_email = settings.WAGTAILADMIN_NOTIFICATION_FROM_EMAIL + elif hasattr(settings, 'DEFAULT_FROM_EMAIL'): + from_email = settings.DEFAULT_FROM_EMAIL + else: + from_email = 'webmaster@localhost' + + send_mail(email_subject, email_content, from_email, email_addresses) diff --git a/wagtail/wagtailadmin/views/pages.py b/wagtail/wagtailadmin/views/pages.py index a707d1df6..e1dd99a58 100644 --- a/wagtail/wagtailadmin/views/pages.py +++ b/wagtail/wagtailadmin/views/pages.py @@ -15,7 +15,8 @@ from django.db.models import Count from wagtail.wagtailadmin.edit_handlers import TabbedInterface, ObjectList from wagtail.wagtailadmin.forms import SearchForm, CopyForm -from wagtail.wagtailadmin import tasks, signals +from wagtail.wagtailadmin.utils import send_notification +from wagtail.wagtailadmin import signals from wagtail.wagtailcore import hooks from wagtail.wagtailcore.models import Page, PageRevision, get_navigation_menu_items @@ -225,7 +226,7 @@ def create(request, content_type_app_name, content_type_model_name, parent_page_ messages.success(request, _("Page '{0}' published.").format(page.title)) elif is_submitting: messages.success(request, _("Page '{0}' submitted for moderation.").format(page.title)) - tasks.send_notification.delay(page.get_latest_revision().id, 'submitted', request.user.id) + send_notification(page.get_latest_revision().id, 'submitted', request.user.id) else: messages.success(request, _("Page '{0}' created.").format(page.title)) @@ -361,7 +362,7 @@ def edit(request, page_id): messages.button(reverse('wagtailadmin_pages_view_draft', args=(page_id,)), _('View draft')), messages.button(reverse('wagtailadmin_pages_edit', args=(page_id,)), _('Edit')) ]) - tasks.send_notification.delay(page.get_latest_revision().id, 'submitted', request.user.id) + send_notification(page.get_latest_revision().id, 'submitted', request.user.id) else: messages.success(request, _("Page '{0}' updated.").format(page.title)) @@ -782,7 +783,7 @@ def approve_moderation(request, revision_id): if request.method == 'POST': revision.approve_moderation() messages.success(request, _("Page '{0}' published.").format(revision.page.title)) - tasks.send_notification.delay(revision.id, 'approved', request.user.id) + send_notification(revision.id, 'approved', request.user.id) return redirect('wagtailadmin_home') @@ -799,7 +800,7 @@ def reject_moderation(request, revision_id): if request.method == 'POST': revision.reject_moderation() messages.success(request, _("Page '{0}' rejected for publication.").format(revision.page.title)) - tasks.send_notification.delay(revision.id, 'rejected', request.user.id) + send_notification(revision.id, 'rejected', request.user.id) return redirect('wagtailadmin_home') diff --git a/wagtail/wagtailforms/models.py b/wagtail/wagtailforms/models.py index 755994dbf..acbdb08b2 100644 --- a/wagtail/wagtailforms/models.py +++ b/wagtail/wagtailforms/models.py @@ -16,7 +16,7 @@ from django.core.serializers.json import DjangoJSONEncoder from wagtail.wagtailcore.models import Page, Orderable, UserPagePermissionsProxy, get_page_types from wagtail.wagtailadmin.edit_handlers import FieldPanel -from wagtail.wagtailadmin import tasks +from wagtail.wagtailadmin.utils import send_email_task from .forms import FormBuilder @@ -194,7 +194,7 @@ class AbstractEmailForm(AbstractForm): if self.to_address: content = '\n'.join([x[1].label + ': ' + form.data.get(x[0]) for x in form.fields.items()]) - tasks.send_email_task.delay(self.subject, content, [self.to_address], self.from_address,) + send_email_task(self.subject, content, [self.to_address], self.from_address,) class Meta: From 378b2c546e6a6044afc377f1e48f9b6f1ff5af75 Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Mon, 30 Mar 2015 14:54:59 +0100 Subject: [PATCH 08/27] Rename send_email_task => send_mail Also make send_notification use send_mail --- wagtail/wagtailadmin/utils.py | 36 +++++++++++++--------------------- wagtail/wagtailforms/models.py | 4 ++-- 2 files changed, 16 insertions(+), 24 deletions(-) diff --git a/wagtail/wagtailadmin/utils.py b/wagtail/wagtailadmin/utils.py index d864507d9..a5cb98a1a 100644 --- a/wagtail/wagtailadmin/utils.py +++ b/wagtail/wagtailadmin/utils.py @@ -1,5 +1,5 @@ from django.template.loader import render_to_string -from django.core.mail import send_mail +from django.core.mail import send_mail as django_send_mail from django.conf import settings from django.contrib.auth import get_user_model from django.db.models import Q @@ -59,6 +59,18 @@ def users_with_page_permission(page, permission_type, include_superusers=True): return User.objects.filter(is_active=True).filter(q).distinct() +def send_mail(email_subject, email_content, email_addresses, from_email=None): + if not from_email: + if hasattr(settings, 'WAGTAILADMIN_NOTIFICATION_FROM_EMAIL'): + from_email = settings.WAGTAILADMIN_NOTIFICATION_FROM_EMAIL + elif hasattr(settings, 'DEFAULT_FROM_EMAIL'): + from_email = settings.DEFAULT_FROM_EMAIL + else: + from_email = 'webmaster@localhost' + + django_send_mail(email_subject, email_content, from_email, email_addresses) + + def send_notification(page_revision_id, notification, excluded_user_id): # Get revision revision = PageRevision.objects.get(id=page_revision_id) @@ -89,25 +101,5 @@ def send_notification(page_revision_id, notification, excluded_user_id): email_subject = rendered_template[0] email_content = '\n'.join(rendered_template[1:]) - # Get from email - if hasattr(settings, 'WAGTAILADMIN_NOTIFICATION_FROM_EMAIL'): - from_email = settings.WAGTAILADMIN_NOTIFICATION_FROM_EMAIL - elif hasattr(settings, 'DEFAULT_FROM_EMAIL'): - from_email = settings.DEFAULT_FROM_EMAIL - else: - from_email = 'webmaster@localhost' - # Send email - send_mail(email_subject, email_content, from_email, email_addresses) - - -def send_email_task(email_subject, email_content, email_addresses, from_email=None): - if not from_email: - if hasattr(settings, 'WAGTAILADMIN_NOTIFICATION_FROM_EMAIL'): - from_email = settings.WAGTAILADMIN_NOTIFICATION_FROM_EMAIL - elif hasattr(settings, 'DEFAULT_FROM_EMAIL'): - from_email = settings.DEFAULT_FROM_EMAIL - else: - from_email = 'webmaster@localhost' - - send_mail(email_subject, email_content, from_email, email_addresses) + send_mail(email_subject, email_content, email_addresses) diff --git a/wagtail/wagtailforms/models.py b/wagtail/wagtailforms/models.py index acbdb08b2..ff3278167 100644 --- a/wagtail/wagtailforms/models.py +++ b/wagtail/wagtailforms/models.py @@ -16,7 +16,7 @@ from django.core.serializers.json import DjangoJSONEncoder from wagtail.wagtailcore.models import Page, Orderable, UserPagePermissionsProxy, get_page_types from wagtail.wagtailadmin.edit_handlers import FieldPanel -from wagtail.wagtailadmin.utils import send_email_task +from wagtail.wagtailadmin.utils import send_mail from .forms import FormBuilder @@ -194,7 +194,7 @@ class AbstractEmailForm(AbstractForm): if self.to_address: content = '\n'.join([x[1].label + ': ' + form.data.get(x[0]) for x in form.fields.items()]) - send_email_task(self.subject, content, [self.to_address], self.from_address,) + send_mail(self.subject, content, [self.to_address], self.from_address,) class Meta: From 3d48ba0cd8dba20d4a68dd54218980888c533621 Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Mon, 30 Mar 2015 14:55:37 +0100 Subject: [PATCH 09/27] Test for wagtailadmin.utils.send_mail --- wagtail/wagtailadmin/tests/tests.py | 41 ++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/wagtail/wagtailadmin/tests/tests.py b/wagtail/wagtailadmin/tests/tests.py index 2adebbfcf..d4af55f36 100644 --- a/wagtail/wagtailadmin/tests/tests.py +++ b/wagtail/wagtailadmin/tests/tests.py @@ -1,10 +1,10 @@ -from django.test import TestCase +from django.test import TestCase, override_settings from django.core.urlresolvers import reverse from django.core import mail from wagtail.tests.utils import WagtailTestUtils from wagtail.wagtailcore.models import Page -from wagtail.wagtailadmin.utils import send_email_task +from wagtail.wagtailadmin.utils import send_mail class TestHome(TestCase, WagtailTestUtils): @@ -56,15 +56,48 @@ class TestEditorHooks(TestCase, WagtailTestUtils): self.assertContains(response, '') -class TestSendEmailTask(TestCase): +class TestSendMail(TestCase): def test_send_email(self): - send_email_task("Test subject", "Test content", ["nobody@email.com"], "test@email.com") + send_mail("Test subject", "Test content", ["nobody@email.com"], "test@email.com") # Check that the email was sent self.assertEqual(len(mail.outbox), 1) self.assertEqual(mail.outbox[0].subject, "Test subject") self.assertEqual(mail.outbox[0].body, "Test content") self.assertEqual(mail.outbox[0].to, ["nobody@email.com"]) + self.assertEqual(mail.outbox[0].from_email, "test@email.com") + + @override_settings(WAGTAILADMIN_NOTIFICATION_FROM_EMAIL='anothertest@email.com') + def test_send_fallback_to_wagtailadmin_notification_from_email_setting(self): + send_mail("Test subject", "Test content", ["nobody@email.com"]) + + # Check that the email was sent + self.assertEqual(len(mail.outbox), 1) + self.assertEqual(mail.outbox[0].subject, "Test subject") + self.assertEqual(mail.outbox[0].body, "Test content") + self.assertEqual(mail.outbox[0].to, ["nobody@email.com"]) + self.assertEqual(mail.outbox[0].from_email, "anothertest@email.com") + + @override_settings(DEFAULT_FROM_EMAIL='yetanothertest@email.com') + def test_send_fallback_to_default_from_email_setting(self): + send_mail("Test subject", "Test content", ["nobody@email.com"]) + + # Check that the email was sent + self.assertEqual(len(mail.outbox), 1) + self.assertEqual(mail.outbox[0].subject, "Test subject") + self.assertEqual(mail.outbox[0].body, "Test content") + self.assertEqual(mail.outbox[0].to, ["nobody@email.com"]) + self.assertEqual(mail.outbox[0].from_email, "yetanothertest@email.com") + + def test_send_default_from_email(self): + send_mail("Test subject", "Test content", ["nobody@email.com"]) + + # Check that the email was sent + self.assertEqual(len(mail.outbox), 1) + self.assertEqual(mail.outbox[0].subject, "Test subject") + self.assertEqual(mail.outbox[0].body, "Test content") + self.assertEqual(mail.outbox[0].to, ["nobody@email.com"]) + self.assertEqual(mail.outbox[0].from_email, "webmaster@localhost") class TestExplorerNavView(TestCase, WagtailTestUtils): From c7cfa7afe7867caaf9964a45bdf494ab4b3d79e9 Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Mon, 30 Mar 2015 16:13:04 +0100 Subject: [PATCH 10/27] Make wagtaildemo available in tests --- wagtail/tests/demosite/__init__.py | 0 wagtail/tests/demosite/fixtures/demosite.json | 1150 +++++++++++++++++ .../tests/demosite/migrations/0001_initial.py | 513 ++++++++ wagtail/tests/demosite/migrations/__init__.py | 0 wagtail/tests/demosite/models.py | 594 +++++++++ wagtail/tests/settings.py | 1 + 6 files changed, 2258 insertions(+) create mode 100644 wagtail/tests/demosite/__init__.py create mode 100644 wagtail/tests/demosite/fixtures/demosite.json create mode 100644 wagtail/tests/demosite/migrations/0001_initial.py create mode 100644 wagtail/tests/demosite/migrations/__init__.py create mode 100644 wagtail/tests/demosite/models.py diff --git a/wagtail/tests/demosite/__init__.py b/wagtail/tests/demosite/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/wagtail/tests/demosite/fixtures/demosite.json b/wagtail/tests/demosite/fixtures/demosite.json new file mode 100644 index 000000000..4c730e064 --- /dev/null +++ b/wagtail/tests/demosite/fixtures/demosite.json @@ -0,0 +1,1150 @@ +[ +{ + "pk": 1, + "model": "wagtailcore.page", + "fields": { + "title": "Root", + "numchild": 1, + "show_in_menus": false, + "live": true, + "seo_title": "", + "depth": 1, + "search_description": "", + "content_type": [ + "wagtailcore", + "page" + ], + "has_unpublished_changes": false, + "owner": null, + "path": "0001", + "url_path": "/", + "slug": "root" + } +}, +{ + "pk": 2, + "model": "wagtailcore.page", + "fields": { + "title": "Home page", + "numchild": 5, + "show_in_menus": true, + "live": true, + "seo_title": "", + "depth": 2, + "search_description": "", + "content_type": [ + "demosite", + "homepage" + ], + "has_unpublished_changes": false, + "owner": null, + "path": "00010002", + "url_path": "/home-page/", + "slug": "home-page" + } +}, +{ + "pk": 4, + "model": "wagtailcore.page", + "fields": { + "title": "Events index", + "numchild": 2, + "show_in_menus": true, + "live": true, + "seo_title": "", + "depth": 3, + "search_description": "", + "content_type": [ + "demosite", + "eventindexpage" + ], + "has_unpublished_changes": false, + "owner": null, + "path": "000100020001", + "url_path": "/home-page/events-index/", + "slug": "events-index" + } +}, +{ + "pk": 5, + "model": "wagtailcore.page", + "fields": { + "title": "Blog index", + "numchild": 3, + "show_in_menus": true, + "live": true, + "seo_title": "", + "depth": 3, + "search_description": "", + "content_type": [ + "demosite", + "blogindexpage" + ], + "has_unpublished_changes": false, + "owner": null, + "path": "000100020002", + "url_path": "/home-page/blog-index/", + "slug": "blog-index" + } +}, +{ + "pk": 6, + "model": "wagtailcore.page", + "fields": { + "title": "Standard index", + "numchild": 4, + "show_in_menus": true, + "live": true, + "seo_title": "", + "depth": 3, + "search_description": "", + "content_type": [ + "demosite", + "standardindexpage" + ], + "has_unpublished_changes": false, + "owner": null, + "path": "000100020003", + "url_path": "/home-page/standard-index/", + "slug": "standard-index" + } +}, +{ + "pk": 8, + "model": "wagtailcore.page", + "fields": { + "title": "Event 1", + "numchild": 0, + "show_in_menus": false, + "live": true, + "seo_title": "", + "depth": 4, + "search_description": "At first glance, the wagtails appear to be divided into a yellow-bellied group and a white-bellied one", + "content_type": [ + "demosite", + "eventpage" + ], + "has_unpublished_changes": false, + "owner": null, + "path": "0001000200010001", + "url_path": "/home-page/events-index/event-1/", + "slug": "event-1" + } +}, +{ + "pk": 9, + "model": "wagtailcore.page", + "fields": { + "title": "Event 2", + "numchild": 0, + "show_in_menus": false, + "live": true, + "seo_title": "", + "depth": 4, + "search_description": "Three species are poly- or paraphyletic in the present taxonomical arrangement and either subspecies need to be reassigned and/or species split up. The Blue-headed Wagtail (AKA Yellow Wagtail and many other names), especially, has always been a taxonomical nightmare with over a dozen currently accepted subspecies and many more invalid ones. The two remaining \"monochrome\" species, Mekong and African Pied Wagtail may be closely related, or a most striking example of convergent evolution.", + "content_type": [ + "demosite", + "eventpage" + ], + "has_unpublished_changes": false, + "owner": null, + "path": "0001000200010002", + "url_path": "/home-page/events-index/event-2/", + "slug": "event-2" + } +}, +{ + "pk": 10, + "model": "wagtailcore.page", + "fields": { + "title": "Standard page 1", + "numchild": 0, + "show_in_menus": true, + "live": true, + "seo_title": "", + "depth": 4, + "search_description": "Wagtails are slender, often colourful, ground-feeding insectivores of open country in the Old World. They are ground nesters.", + "content_type": [ + "demosite", + "standardpage" + ], + "has_unpublished_changes": false, + "owner": null, + "path": "0001000200030001", + "url_path": "/home-page/standard-index/standard-page-1/", + "slug": "standard-page-1" + } +}, +{ + "pk": 12, + "model": "wagtailcore.page", + "fields": { + "title": "Contact page", + "numchild": 0, + "show_in_menus": true, + "live": true, + "seo_title": "", + "depth": 3, + "search_description": "The origin of the genus appears to be in the general area of Eastern Siberia/Mongolia. Wagtails spread rapidly across Eurasia and dispersed to Africa in the Zanclean...", + "content_type": [ + "demosite", + "contactpage" + ], + "has_unpublished_changes": false, + "owner": null, + "path": "000100020005", + "url_path": "/home-page/contact-page/", + "slug": "contact-page" + } +}, +{ + "pk": 13, + "model": "wagtailcore.page", + "fields": { + "title": "James Joyce", + "numchild": 0, + "show_in_menus": true, + "live": true, + "seo_title": "", + "depth": 4, + "search_description": "The origin of the genus appears to be in the general area of Eastern Siberia/Mongolia. Wagtails spread rapidly across Eurasia and dispersed to Africa", + "content_type": [ + "demosite", + "personpage" + ], + "has_unpublished_changes": false, + "owner": null, + "path": "0001000200040001", + "url_path": "/home-page/people/james-joyce/", + "slug": "james-joyce" + } +}, +{ + "pk": 14, + "model": "wagtailcore.page", + "fields": { + "title": "David Mitchell", + "numchild": 0, + "show_in_menus": true, + "live": true, + "seo_title": "", + "depth": 4, + "search_description": "Recent studies have suggested instead that it is a signal of vigilance that may aid to deter potential predators.", + "content_type": [ + "demosite", + "personpage" + ], + "has_unpublished_changes": false, + "owner": null, + "path": "0001000200040002", + "url_path": "/home-page/people/david-mitchell/", + "slug": "david-mitchell" + } +}, +{ + "pk": 15, + "model": "wagtailcore.page", + "fields": { + "title": "Standard page 2", + "numchild": 0, + "show_in_menus": true, + "live": true, + "seo_title": "", + "depth": 4, + "search_description": "The remaining five species are highly variable morphologically and their relationships with each other and with the two clades have not yet been satisfactorily explained.", + "content_type": [ + "demosite", + "standardpage" + ], + "has_unpublished_changes": false, + "owner": null, + "path": "0001000200030002", + "url_path": "/home-page/standard-index/standard-page-2/", + "slug": "standard-page-2" + } +}, +{ + "pk": 16, + "model": "wagtailcore.page", + "fields": { + "title": "Blog post", + "numchild": 0, + "show_in_menus": false, + "live": true, + "seo_title": "", + "depth": 4, + "search_description": "The origin of the genus appears to be in the general area of Eastern Siberia/Mongolia. Wagtails spread rapidly across Eurasia and dispersed to Africa in the Zanclean (Early Pliocene) where the sub-Saharan lineage was later isolated. The African Pied Wagtail (and possibly the Mekong Wagtail) diverged prior to the massive radiation of the white-bellied black-throated and most yellow-bellied forms, all of which took place during the late Piacenzian (early Late Pliocene), c. 3 mya.", + "content_type": [ + "demosite", + "blogentrypage" + ], + "has_unpublished_changes": false, + "owner": null, + "path": "0001000200020001", + "url_path": "/home-page/blog-index/blog-post/", + "slug": "blog-post" + } +}, +{ + "pk": 17, + "model": "wagtailcore.page", + "fields": { + "title": "Photo credits", + "numchild": 0, + "show_in_menus": false, + "live": true, + "seo_title": "", + "depth": 4, + "search_description": "", + "content_type": [ + "demosite", + "standardpage" + ], + "has_unpublished_changes": false, + "owner": null, + "path": "0001000200030007", + "url_path": "/home-page/standard-index/photo-credits/", + "slug": "photo-credits" + } +}, +{ + "pk": 18, + "model": "wagtailcore.page", + "fields": { + "title": "Blog post again", + "numchild": 0, + "show_in_menus": false, + "live": true, + "seo_title": "", + "depth": 4, + "search_description": "Wagtails are slender, often colourful, ground-feeding insectivores of open country in the Old World. They are ground nesters, laying up to six speckled eggs at a time. Among their most conspicuous behaviours is a near constant tail wagging, a trait that has given the birds their common name. In spite of the ubiquity of the behaviour and observations of it, the reasons for it are poorly understood. It has been suggested that it may flush up prey, or that it may signal submissiveness to other wagtails. Recent studies have suggested instead that it is a signal of vigilance that may aid to deter potential predators.", + "content_type": [ + "demosite", + "blogentrypage" + ], + "has_unpublished_changes": false, + "owner": null, + "path": "0001000200020002", + "url_path": "/home-page/blog-index/blog-post-again/", + "slug": "blog-post-again" + } +}, +{ + "pk": 19, + "model": "wagtailcore.page", + "fields": { + "title": "Another blog post", + "numchild": 0, + "show_in_menus": false, + "live": true, + "seo_title": "", + "depth": 4, + "search_description": "Three species are poly- or paraphyletic in the present taxonomical arrangement and either subspecies need to be reassigned and/or species split up. The Blue-headed Wagtail (AKA Yellow Wagtail and many other names), especially, has always been a taxonomical nightmare with over a dozen currently accepted subspecies and many more invalid ones. The two remaining \"monochrome\" species, Mekong and African Pied Wagtail may be closely related, or a most striking example of convergent evolution.", + "content_type": [ + "demosite", + "blogentrypage" + ], + "has_unpublished_changes": false, + "owner": null, + "path": "0001000200020003", + "url_path": "/home-page/blog-index/another-blog-post/", + "slug": "another-blog-post" + } +}, +{ + "pk": 20, + "model": "wagtailcore.page", + "fields": { + "title": "People", + "numchild": 2, + "show_in_menus": true, + "live": true, + "seo_title": "", + "depth": 3, + "search_description": "", + "content_type": [ + "demosite", + "standardindexpage" + ], + "has_unpublished_changes": false, + "owner": null, + "path": "000100020004", + "url_path": "/home-page/people/", + "slug": "people" + } +}, +{ + "pk": 21, + "model": "wagtailcore.page", + "fields": { + "title": "A deeper menu level", + "numchild": 2, + "show_in_menus": true, + "live": true, + "seo_title": "", + "depth": 4, + "search_description": "", + "content_type": [ + "demosite", + "standardindexpage" + ], + "has_unpublished_changes": false, + "owner": null, + "path": "0001000200030008", + "url_path": "/home-page/standard-index/a-deeper-menu-level/", + "slug": "a-deeper-menu-level" + } +}, +{ + "pk": 22, + "model": "wagtailcore.page", + "fields": { + "title": "A grandchild page", + "numchild": 0, + "show_in_menus": true, + "live": true, + "seo_title": "", + "depth": 5, + "search_description": "The origin of the genus appears to be in the general area of Eastern Siberia/Mongolia. Wagtails spread rapidly across Eurasia and dispersed to Africa in the Zanclean (Early Pliocene) where the sub-Saharan lineage was later isolated. The African Pied Wagtail (and possibly the Mekong Wagtail) diverged prior to the massive radiation of the white-bellied black-throated and most yellow-bellied forms, all of which took place during the late Piacenzian (early Late Pliocene), c. 3 mya.", + "content_type": [ + "demosite", + "standardpage" + ], + "has_unpublished_changes": false, + "owner": null, + "path": "00010002000300080001", + "url_path": "/home-page/standard-index/a-deeper-menu-level/a-grandchild-page/", + "slug": "a-grandchild-page" + } +}, +{ + "pk": 23, + "model": "wagtailcore.page", + "fields": { + "title": "Another grandchild page", + "numchild": 0, + "show_in_menus": true, + "live": true, + "seo_title": "", + "depth": 5, + "search_description": "The origin of the genus appears to be in the general area of Eastern Siberia/Mongolia. Wagtails spread rapidly across Eurasia and dispersed to Africa in the Zanclean (Early Pliocene) where the sub-Saharan lineage was later isolated. The African Pied Wagtail (and possibly the Mekong Wagtail) diverged prior to the massive radiation of the white-bellied black-throated and most yellow-bellied forms, all of which took place during the late Piacenzian (early Late Pliocene), c. 3 mya.", + "content_type": [ + "demosite", + "standardpage" + ], + "has_unpublished_changes": false, + "owner": null, + "path": "00010002000300080002", + "url_path": "/home-page/standard-index/a-deeper-menu-level/another-grandchild-page/", + "slug": "another-grandchild-page" + } +}, +{ + "pk": 4, + "model": "wagtailimages.image", + "fields": { + "title": "Wagtail by mark Harkin", + "created_at": "2014-02-06T10:14:47.173Z", + "height": 427, + "width": 640, + "file": "original_images/wagtail_by_markyharky.jpg", + "uploaded_by_user": null + } +}, +{ + "pk": 5, + "model": "wagtailimages.image", + "fields": { + "title": "James Joyce", + "created_at": "2014-02-06T10:37:10.518Z", + "height": 392, + "width": 500, + "file": "original_images/James_Joyce_in_1915.jpg", + "uploaded_by_user": null + } +}, +{ + "pk": 6, + "model": "wagtailimages.image", + "fields": { + "title": "David Mitchell", + "created_at": "2014-02-06T10:42:46.536Z", + "height": 282, + "width": 360, + "file": "original_images/David_Mitchell_by_Kubik.JPG", + "uploaded_by_user": null + } +}, +{ + "pk": 7, + "model": "wagtailimages.image", + "fields": { + "title": "Wagtail by joe Buckingham", + "created_at": "2014-02-06T10:49:29.579Z", + "height": 397, + "width": 640, + "file": "original_images/wagtail_by_joe_buckingham.jpg", + "uploaded_by_user": null + } +}, +{ + "pk": 8, + "model": "wagtailimages.image", + "fields": { + "title": "Wagtail by fs-phil", + "created_at": "2014-02-06T10:54:29.963Z", + "height": 397, + "width": 640, + "file": "original_images/wagtail_by_fs-phil.jpg", + "uploaded_by_user": null + } +}, +{ + "pk": 9, + "model": "wagtailimages.image", + "fields": { + "title": "White wagtail by Koshy Koshy", + "created_at": "2014-02-06T10:57:05.536Z", + "height": 397, + "width": 640, + "file": "original_images/white_wagtail_by_Koshyk.jpg", + "uploaded_by_user": null + } +}, +{ + "pk": 10, + "model": "wagtailimages.image", + "fields": { + "title": "Pied wagtail by Marie Hale", + "created_at": "2014-02-06T11:05:12.370Z", + "height": 397, + "width": 640, + "file": "original_images/pied_wagtail_by_Marie_Hale.jpg", + "uploaded_by_user": null + } +}, +{ + "pk": 11, + "model": "wagtailimages.image", + "fields": { + "title": "Wagtail at Borovoye, Kazakhstan by Ken and Nyetta", + "created_at": "2014-02-06T11:08:09.355Z", + "height": 397, + "width": 640, + "file": "original_images/wagtail_at_Borovoye_Kazakhstan_by_Ken_and_Nyetta.jpg", + "uploaded_by_user": null + } +}, +{ + "pk": 12, + "model": "wagtailimages.image", + "fields": { + "title": "Wagtail sproing by Jim Bendon", + "created_at": "2014-02-06T11:10:01.185Z", + "height": 397, + "width": 640, + "file": "original_images/wagtail_sproing_by_Jim_Bendon.jpg", + "uploaded_by_user": null + } +}, +{ + "pk": 13, + "model": "wagtailimages.image", + "fields": { + "title": "Hopalong wagtail by Ruth Flickr", + "created_at": "2014-02-06T11:15:32.454Z", + "height": 397, + "width": 640, + "file": "original_images/hopalong_wagtail_by_Ruth_Flickr.jpg", + "uploaded_by_user": null + } +}, +{ + "pk": 14, + "model": "wagtailimages.image", + "fields": { + "title": "Wagtail collects insects by Margrit", + "created_at": "2014-02-06T11:21:13.596Z", + "height": 397, + "width": 640, + "file": "original_images/wagtail_collects_insects_by_Maggi_94.jpg", + "uploaded_by_user": null + } +}, +{ + "pk": 15, + "model": "wagtailimages.image", + "fields": { + "title": "Grey wagtail by Lip Kee", + "created_at": "2014-02-06T11:23:36.409Z", + "height": 397, + "width": 640, + "file": "original_images/grey_wagtail_by_lip_kee.jpg", + "uploaded_by_user": null + } +}, +{ + "pk": 5, + "model": "demosite.blogindexpage", + "fields": { + "intro": "

Three species are poly- or paraphyletic in the present taxonomical arrangement and either subspecies need to be reassigned and/or species split up. The Blue-headed Wagtail (AKA Yellow Wagtail and many other names), especially, has always been a taxonomical nightmare with over a dozen currently accepted subspecies and many more invalid ones. The two remaining \"monochrome\" species, Mekong and African Pied Wagtail may be closely related, or a most striking example of convergent evolution.

" + } +}, +{ + "pk": 1, + "model": "demosite.blogindexpagerelatedlink", + "fields": { + "link_page": 4, + "title": "Events index", + "link_external": "", + "sort_order": 0, + "link_document": null, + "page": 5 + } +}, +{ + "pk": 16, + "model": "demosite.blogentrypage", + "fields": { + "body": "

mtDNA cytochrome b and NADH dehydrogenase subunit 2 sequence data (Voelker, 2002) is of limited use: the suspicion that there is a superspecies of probably 3 white-bellied, black-throated wagtails is confirmed. Also, there is another superspecies in sub-Saharan Africa, three white-throated species with a black breast-band. The remaining five species are highly variable morphologically and their relationships with each other and with the two clades have not yet been satisfactorily explained.

The origin of the genus appears to be in the general area of Eastern Siberia/Mongolia. Wagtails spread rapidly across Eurasia and dispersed to Africa in the Zanclean (Early Pliocene) where the sub-Saharan lineage was later isolated. The African Pied Wagtail (and possibly the Mekong Wagtail) diverged prior to the massive radiation of the white-bellied black-throated and most yellow-bellied forms, all of which took place during the late Piacenzian (early Late Pliocene), c. 3 mya.


mtDNA cytochrome b and NADH dehydrogenase subunit 2 sequence data (Voelker, 2002) is of limited use: the suspicion that there is a superspecies of probably 3 white-bellied, black-throated wagtails is confirmed. Also, there is another superspecies in sub-Saharan Africa, three white-throated species with a black breast-band. The remaining five species are highly variable morphologically and their relationships with each other and with the two clades have not yet been satisfactorily explained.

The origin of the genus appears to be in the general area of Eastern Siberia/Mongolia. Wagtails spread rapidly across Eurasia and dispersed to Africa in the Zanclean (Early Pliocene) where the sub-Saharan lineage was later isolated. The African Pied Wagtail (and possibly the Mekong Wagtail) diverged prior to the massive radiation of the white-bellied black-throated and most yellow-bellied forms, all of which took place during the late Piacenzian (early Late Pliocene), c. 3 mya.

mtDNA cytochrome b and NADH dehydrogenase subunit 2 sequence data (Voelker, 2002) is of limited use: the suspicion that there is a superspecies of probably 3 white-bellied, black-throated wagtails is confirmed. Also, there is another superspecies in sub-Saharan Africa, three white-throated species with a black breast-band. The remaining five species are highly variable morphologically and their relationships with each other and with the two clades have not yet been satisfactorily explained.

The origin of the genus appears to be in the general area of Eastern Siberia/Mongolia. Wagtails spread rapidly across Eurasia and dispersed to Africa in the Zanclean (Early Pliocene) where the sub-Saharan lineage was later isolated. The African Pied Wagtail (and possibly the Mekong Wagtail) diverged prior to the massive radiation of the white-bellied black-throated and most yellow-bellied forms, all of which took place during the late Piacenzian (early Late Pliocene), c. 3 mya.

", + "date": "2013-12-02", + "feed_image": 7 + } +}, +{ + "pk": 18, + "model": "demosite.blogentrypage", + "fields": { + "body": "

Wagtails are slender, often colourful, ground-feeding insectivores of open country in the Old World. They are ground nesters, laying up to six speckled eggs at a time. Among their most conspicuous behaviours is a near constant tail wagging, a trait that has given the birds their common name. In spite of the ubiquity of the behaviour and observations of it, the reasons for it are poorly understood. It has been suggested that it may flush up prey, or that it may signal submissiveness to other wagtails. Recent studies have suggested instead that it is a signal of vigilance that may aid to deter potential predators.




At first glance, the wagtails appear to be divided into a yellow-bellied group and a white-bellied one, or one where the upper head is black and another where it is usually gray, but may be olive, yellow, or other colours. However, these are not evolutionary lineages; change of belly colour and increase of melanin have occurred independently several times in the wagtails, and the colour patterns which actually indicate relationships are more subtle.


mtDNA cytochrome b and NADH dehydrogenase subunit 2 sequence data (Voelker, 2002) is of limited use: the suspicion that there is a superspecies of probably 3 white-bellied, black-throated wagtails is confirmed. Also, there is another superspecies in sub-Saharan Africa, three white-throated species with a black breast-band. The remaining five species are highly variable morphologically and their relationships with each other and with the two clades have not yet been satisfactorily explained.


The origin of the genus appears to be in the general area of Eastern Siberia/Mongolia. Wagtails spread rapidly across Eurasia and dispersed to Africa in the Zanclean (Early Pliocene) where the sub-Saharan lineage was later isolated. The African Pied Wagtail (and possibly the Mekong Wagtail) diverged prior to the massive radiation of the white-bellied black-throated and most yellow-bellied forms, all of which took place during the late Piacenzian (early Late Pliocene), c. 3 mya.


Three species are poly- or paraphyletic in the present taxonomical arrangement and either subspecies need to be reassigned and/or species split up. The Blue-headed Wagtail (AKA Yellow Wagtail and many other names), especially, has always been a taxonomical nightmare with over a dozen currently accepted subspecies and many more invalid ones. The two remaining \"monochrome\" species, Mekong and African Pied Wagtail may be closely related, or a most striking example of convergent evolution.


Prehistoric wagtails known from fossils are Motacilla humata and Motacilla major.


See the species accounts for more on individual species' relationships.

", + "date": "2014-01-10", + "feed_image": 15 + } +}, +{ + "pk": 19, + "model": "demosite.blogentrypage", + "fields": { + "body": "

Wagtails are slender, often colourful, ground-feeding insectivores of open country in the Old World. They are ground nesters, laying up to six speckled eggs at a time. Among their most conspicuous behaviours is a near constant tail wagging, a trait that has given the birds their common name. In spite of the ubiquity of the behaviour and observations of it, the reasons for it are poorly understood. It has been suggested that it may flush up prey, or that it may signal submissiveness to other wagtails. Recent studies have suggested instead that it is a signal of vigilance that may aid to deter potential predators.


At first glance, the wagtails appear to be divided into a yellow-bellied group and a white-bellied one, or one where the upper head is black and another where it is usually gray, but may be olive, yellow, or other colours. However, these are not evolutionary lineages; change of belly colour and increase of melanin have occurred independently several times in the wagtails, and the colour patterns which actually indicate relationships are more subtle.


mtDNA cytochrome b and NADH dehydrogenase subunit 2 sequence data (Voelker, 2002) is of limited use: the suspicion that there is a superspecies of probably 3 white-bellied, black-throated wagtails is confirmed. Also, there is another superspecies in sub-Saharan Africa, three white-throated species with a black breast-band. The remaining five species are highly variable morphologically and their relationships with each other and with the two clades have not yet been satisfactorily explained.


The origin of the genus appears to be in the general area of Eastern Siberia/Mongolia. Wagtails spread rapidly across Eurasia and dispersed to Africa in the Zanclean (Early Pliocene) where the sub-Saharan lineage was later isolated. The African Pied Wagtail (and possibly the Mekong Wagtail) diverged prior to the massive radiation of the white-bellied black-throated and most yellow-bellied forms, all of which took place during the late Piacenzian (early Late Pliocene), c. 3 mya.


Three species are poly- or paraphyletic in the present taxonomical arrangement and either subspecies need to be reassigned and/or species split up. The Blue-headed Wagtail (AKA Yellow Wagtail and many other names), especially, has always been a taxonomical nightmare with over a dozen currently accepted subspecies and many more invalid ones. The two remaining \"monochrome\" species, Mekong and African Pied Wagtail may be closely related, or a most striking example of convergent evolution.


Prehistoric wagtails known from fossils are Motacilla humata and Motacilla major.


See the species accounts for more on individual species' relationships.

", + "date": "2014-02-01", + "feed_image": 14 + } +}, +{ + "pk": 1, + "model": "demosite.blogentrypagecarouselitem", + "fields": { + "link_page": null, + "embed_url": "", + "image": 9, + "link_external": "http://www.flickr.com/photos/kkoshy/", + "caption": "White wagtail by Koshy Koshy", + "sort_order": 0, + "link_document": null, + "page": 16 + } +}, +{ + "pk": 2, + "model": "demosite.blogentrypagecarouselitem", + "fields": { + "link_page": null, + "embed_url": "", + "image": 7, + "link_external": "http://www.flickr.com/photos/jim_bendon_1957/", + "caption": "Wagtail by Jim Bendon", + "sort_order": 1, + "link_document": null, + "page": 16 + } +}, +{ + "pk": 4, + "model": "demosite.blogentrypagetag", + "fields": { + "content_object": 19, + "tag": 5 + } +}, +{ + "pk": 5, + "model": "demosite.blogentrypagetag", + "fields": { + "content_object": 16, + "tag": 4 + } +}, +{ + "pk": 6, + "model": "demosite.blogentrypagetag", + "fields": { + "content_object": 16, + "tag": 5 + } +}, +{ + "pk": 7, + "model": "demosite.blogentrypagetag", + "fields": { + "content_object": 18, + "tag": 4 + } +}, +{ + "pk": 12, + "model": "demosite.contactpage", + "fields": { + "body": "

Wagtails are slender, often colourful, ground-feeding insectivores of open country in the Old World. They are ground nesters, laying up to six speckled eggs at a time. Among their most conspicuous behaviours is a near constant tail wagging, a trait that has given the birds their common name. In spite of the ubiquity of the behaviour and observations of it, the reasons for it are poorly understood. It has been suggested that it may flush up prey, or that it may signal submissiveness to other wagtails. Recent studies have suggested instead that it is a signal of vigilance that may aid to deter potential predators.

", + "city": "Birdland", + "post_code": "W1A 1AA", + "country": "Birdshire", + "telephone": "012345 123456", + "address_1": "21 Tweety Mansions", + "address_2": "3 Bird Lane", + "email": "foo@example.com", + "feed_image": 7 + } +}, +{ + "pk": 4, + "model": "demosite.eventindexpage", + "fields": { + "intro": "

Three species are poly- or paraphyletic in the present taxonomical arrangement and either subspecies need to be reassigned and/or species split up. The Blue-headed Wagtail (AKA Yellow Wagtail and many other names), especially, has always been a taxonomical nightmare with over a dozen currently accepted subspecies and many more invalid ones. The two remaining \"monochrome\" species, Mekong and African Pied Wagtail may be closely related, or a most striking example of convergent evolution.

" + } +}, +{ + "pk": 8, + "model": "demosite.eventpage", + "fields": { + "body": "

Wagtails are slender, often colourful, ground-feeding insectivores of open country in the Old World. They are ground nesters, laying up to six speckled eggs at a time. Among their most conspicuous behaviours is a near constant tail wagging, a trait that has given the birds their common name. In spite of the ubiquity of the behaviour and observations of it, the reasons for it are poorly understood. It has been suggested that it may flush up prey, or that it may signal submissiveness to other wagtails. Recent studies have suggested instead that it is a signal of vigilance that may aid to deter potential predators.

At first glance, the wagtails appear to be divided into a yellow-bellied group and a white-bellied one, or one where the upper head is black and another where it is usually gray, but may be olive, yellow, or other colours. However, these are not evolutionary lineages; change of belly colour and increase of melanin have occurred independently several times in the wagtails, and the colour patterns which actually indicate relationships are more subtle.

", + "feed_image": 8, + "date_from": "2018-02-28", + "time_from": "11:30:00", + "audience": "public", + "cost": "\u00a330 per person, \u00a310 concessions", + "location": "Royal Albert Hall", + "date_to": "2018-03-02", + "time_to": "19:00:00", + "signup_link": "http://www.eventbrite.com/" + } +}, +{ + "pk": 9, + "model": "demosite.eventpage", + "fields": { + "body": "

Three species are poly- or paraphyletic in the present taxonomical arrangement and either subspecies need to be reassigned and/or species split up. The Blue-headed Wagtail (AKA Yellow Wagtail and many other names), especially, has always been a taxonomical nightmare with over a dozen currently accepted subspecies and many more invalid ones. The two remaining \"monochrome\" species, Mekong and African Pied Wagtail may be closely related, or a most striking example of convergent evolution

", + "feed_image": 10, + "date_from": "2018-04-26", + "time_from": null, + "audience": "private", + "cost": "\u00a350", + "location": "O2 Arena", + "date_to": null, + "time_to": null, + "signup_link": "" + } +}, +{ + "pk": 1, + "model": "demosite.eventpagespeaker", + "fields": { + "last_name": "Joyce", + "first_name": "James", + "link_page": null, + "image": 5, + "link_external": "", + "sort_order": 0, + "link_document": null, + "page": 8 + } +}, +{ + "pk": 2, + "model": "demosite.eventpagespeaker", + "fields": { + "last_name": "Mitchell", + "first_name": "David", + "link_page": null, + "image": 6, + "link_external": "", + "sort_order": 1, + "link_document": null, + "page": 8 + } +}, +{ + "pk": 2, + "model": "demosite.homepage", + "fields": { + "body": "

Wagtails are slender, often colourful, ground-feeding insectivores of open country in the Old World. They are ground nesters, laying up to six speckled eggs at a time. Among their most conspicuous behaviours is a near constant tail wagging, a trait that has given the birds their common name. In spite of the ubiquity of the behaviour and observations of it, the reasons for it are poorly understood. It has been suggested that it may flush up prey, or that it may signal submissiveness to other wagtails. Recent studies have suggested instead that it is a signal of vigilance that may aid to deter potential predators.

" + } +}, +{ + "pk": 1, + "model": "demosite.homepagecarouselitem", + "fields": { + "link_page": null, + "embed_url": "", + "image": 15, + "link_external": "http://www.flickr.com/photos/lipkee/", + "caption": "Grey wagtail by Lip Kee", + "sort_order": 0, + "link_document": null, + "page": 2 + } +}, +{ + "pk": 2, + "model": "demosite.homepagecarouselitem", + "fields": { + "link_page": null, + "embed_url": "", + "image": 12, + "link_external": "http://www.flickr.com/photos/jim_bendon_1957/", + "caption": "Wagtail sproing by Jim Bendon", + "sort_order": 1, + "link_document": null, + "page": 2 + } +}, +{ + "pk": 3, + "model": "demosite.homepagecarouselitem", + "fields": { + "link_page": null, + "embed_url": "", + "image": 11, + "link_external": "http://www.flickr.com/photos/kjfnjy/", + "caption": "Wagtail at Borovoye, Kazakhstan by Ken and Nyetta", + "sort_order": 2, + "link_document": null, + "page": 2 + } +}, +{ + "pk": 13, + "model": "demosite.personpage", + "fields": { + "feed_image": 5, + "city": "Birdland", + "first_name": "James", + "post_code": "W1A 1AA", + "country": "Birdshire", + "image": 5, + "telephone": "012345 123456", + "last_name": "Joyce", + "address_1": "21 Tweety Mansions", + "address_2": "3 Bird Lane", + "intro": "

The origin of the genus appears to be in the general area of Eastern Siberia/Mongolia. Wagtails spread rapidly across Eurasia and dispersed to Africa in the Zanclean

", + "email": "foo@example.com", + "biography": "

Wagtails are slender, often colourful, ground-feeding insectivores of open country in the Old World. They are ground nesters, laying up to six speckled eggs at a time. Among their most conspicuous behaviours is a near constant tail wagging, a trait that has given the birds their common name. In spite of the ubiquity of the behaviour and observations of it, the reasons for it are poorly understood. It has been suggested that it may flush up prey, or that it may signal submissiveness to other wagtails. Recent studies have suggested instead that it is a signal of vigilance that may aid to deter potential predators.


At first glance, the wagtails appear to be divided into a yellow-bellied group and a white-bellied one, or one where the upper head is black and another where it is usually gray, but may be olive, yellow, or other colours. However, these are not evolutionary lineages; change of belly colour and increase of melanin have occurred independently several times in the wagtails, and the colour patterns which actually indicate relationships are more subtle.

" + } +}, +{ + "pk": 14, + "model": "demosite.personpage", + "fields": { + "feed_image": 6, + "city": "", + "first_name": "David", + "post_code": "W1A 1AA", + "country": "", + "image": 6, + "telephone": "", + "last_name": "Mitchell", + "address_1": "", + "address_2": "", + "intro": "

Wagtails are slender, often colourful, ground-feeding insectivores of open country in the Old World.

", + "email": "foo@example.com", + "biography": "

Wagtails are slender, often colourful, ground-feeding insectivores of open country in the Old World. They are ground nesters, laying up to six speckled eggs at a time. Among their most conspicuous behaviours is a near constant tail wagging, a trait that has given the birds their common name. In spite of the ubiquity of the behaviour and observations of it, the reasons for it are poorly understood. It has been suggested that it may flush up prey, or that it may signal submissiveness to other wagtails. Recent studies have suggested instead that it is a signal of vigilance that may aid to deter potential predators.

" + } +}, +{ + "pk": 6, + "model": "demosite.standardindexpage", + "fields": { + "feed_image": null, + "intro": "

Three species are poly- or paraphyletic in the present taxonomical arrangement and either subspecies need to be reassigned and/or species split up. The Blue-headed Wagtail (AKA Yellow Wagtail and many other names), especially, has always been a taxonomical nightmare with over a dozen currently accepted subspecies and many more invalid ones. The two remaining \"monochrome\" species, Mekong and African Pied Wagtail may be closely related, or a most striking example of convergent evolution.

" + } +}, +{ + "pk": 20, + "model": "demosite.standardindexpage", + "fields": { + "feed_image": null, + "intro": "" + } +}, +{ + "pk": 21, + "model": "demosite.standardindexpage", + "fields": { + "feed_image": null, + "intro": "

A listing of pages at the next level down

" + } +}, +{ + "pk": 10, + "model": "demosite.standardpage", + "fields": { + "body": "

Wagtails are slender, often colourful, ground-feeding insectivores of open country in the Old World. They are ground nesters, laying up to six speckled eggs at a time. Among their most conspicuous behaviours is a near constant tail wagging, a trait that has given the birds their common name. In spite of the ubiquity of the behaviour and observations of it, the reasons for it are poorly understood. It has been suggested that it may flush up prey, or that it may signal submissiveness to other wagtails. Recent studies have suggested instead that it is a signal of vigilance that may aid to deter potential predators.


At first glance, the wagtails appear to be divided into a yellow-bellied group and a white-bellied one, or one where the upper head is black and another where it is usually gray, but may be olive, yellow, or other colours. However, these are not evolutionary lineages; change of belly colour and increase of melanin have occurred independently several times in the wagtails, and the colour patterns which actually indicate relationships are more subtle.


mtDNA cytochrome b and NADH dehydrogenase subunit 2 sequence data (Voelker, 2002) is of limited use: the suspicion that there is a superspecies of probably 3 white-bellied, black-throated wagtails is confirmed. Also, there is another superspecies in sub-Saharan Africa, three white-throated species with a black breast-band. The remaining five species are highly variable morphologically and their relationships with each other and with the two clades have not yet been satisfactorily explained.


The origin of the genus appears to be in the general area of Eastern Siberia/Mongolia. Wagtails spread rapidly across Eurasia and dispersed to Africa in the Zanclean (Early Pliocene) where the sub-Saharan lineage was later isolated. The African Pied Wagtail (and possibly the Mekong Wagtail) diverged prior to the massive radiation of the white-bellied black-throated and most yellow-bellied forms, all of which took place during the late Piacenzian (early Late Pliocene), c. 3 mya.

", + "feed_image": 12, + "intro": "

At first glance, the wagtails appear to be divided into a yellow-bellied group and a white-bellied one, or one where the upper head is black and another where it is usually gray, but may be olive, yellow, or other colours. However, these are not evolutionary lineages; change of belly colour and increase of melanin have occurred independently several times in the wagtails, and the colour patterns which actually indicate relationships are more subtle.

" + } +}, +{ + "pk": 15, + "model": "demosite.standardpage", + "fields": { + "body": "

Wagtails are great

At first glance, the wagtails appear to be divided into a yellow-bellied group and a white-bellied one, or one where the upper head is black and another where it is usually gray, but may be olive, yellow, or other colours. However, these are not evolutionary lineages; change of belly colour and increase of melanin have occurred independently several times in the wagtails, and the colour patterns which actually indicate relationships are more subtle.


Wagtails are pretty

mtDNA cytochrome b and NADH dehydrogenase subunit 2 sequence data (Voelker, 2002) is of limited use: the suspicion that there is a superspecies of probably 3 white-bellied, black-throated wagtails is confirmed. Also, there is another superspecies in sub-Saharan Africa, three white-throated species with a black breast-band. The remaining five species are highly variable morphologically and their relationships with each other and with the two clades have not yet been satisfactorily explained.


The origin of the genus appears to be in the general area of Eastern Siberia/Mongolia. Wagtails spread rapidly across Eurasia and dispersed to Africa in the Zanclean (Early Pliocene) where the sub-Saharan lineage was later isolated. The African Pied Wagtail (and possibly the Mekong Wagtail) diverged prior to the massive radiation of the white-bellied black-throated and most yellow-bellied forms, all of which took place during the late Piacenzian (early Late Pliocene), c. 3 mya.

Three species are poly- or paraphyletic in the present taxonomical arrangement and either subspecies need to be reassigned and/or species split up. The Blue-headed Wagtail (AKA Yellow Wagtail and many other names), especially, has always been a taxonomical nightmare with over a dozen currently accepted subspecies and many more invalid ones. The two remaining \"monochrome\" species, Mekong and African Pied Wagtail may be closely related, or a most striking example of convergent evolution.

", + "feed_image": 10, + "intro": "

The remaining five species are highly variable morphologically and their relationships with each other and with the two clades have not yet been satisfactorily explained.

" + } +}, +{ + "pk": 17, + "model": "demosite.standardpage", + "fields": { + "body": "

James Joyce,\u00a01915,\u00a0Cornell Joyce Collection\u00a0by C. Ruf - public domain in the United States

\n

David Mitchell (b. 1969), British writer,\u00a0Warsaw (Poland), April 7, 2006, \u00a0Mariusz Kubik, GDFL licence

Wagtail,\u00a0October 14, 2012\u00a0by Mark Harkin, \u00a0\u00a0Creative Commons

Wagtail, February 18th 2008, by Joe Buckingham, Creative Commons

Wagtail, August 4th 2009, by fs-phil, Creative Commons

White wagtail, February 5th 2012, by Koshy Koshy, Creative Commons

Pied wagtail, January 20th 2013, by Marie Hale, Creative Commons

Wagtail at Borovoye, Kazakhstan, June 16th 2012, by Ken and Nyetta,\u00a0Creative Commons

Wagtail sproing, April 29 2012, by Jim Bendon, Creative Commons

Hopalong wagtail, June 17th 2008, by Ruth Flickr, Creative Commons

Wagtail collects insects, June 10th 2010, by Margrit, Creative Commons

Grey wagtail, March 13th 2009, by Lip Kee, Creative Commons

", + "feed_image": 15, + "intro": "

The following photos have been used in the sample wagtailapi tests database

" + } +}, +{ + "pk": 22, + "model": "demosite.standardpage", + "fields": { + "body": "

The origin of the genus appears to be in the general area of Eastern Siberia/Mongolia. Wagtails spread rapidly across Eurasia and dispersed to Africa in the Zanclean (Early Pliocene) where the sub-Saharan lineage was later isolated. The African Pied Wagtail (and possibly the Mekong Wagtail) diverged prior to the massive radiation of the white-bellied black-throated and most yellow-bellied forms, all of which took place during the late Piacenzian (early Late Pliocene), c. 3 mya.


Three species are poly- or paraphyletic in the present taxonomical arrangement and either subspecies need to be reassigned and/or species split up. The Blue-headed Wagtail (AKA Yellow Wagtail and many other names), especially, has always been a taxonomical nightmare with over a dozen currently accepted subspecies and many more invalid ones. The two remaining \"monochrome\" species, Mekong and African Pied Wagtail may be closely related, or a most striking example of convergent evolution.

", + "feed_image": null, + "intro": "

At first glance, the wagtails appear to be divided into a yellow-bellied group and a white-bellied one, or one where the upper head is black and another where it is usually gray, but may be olive, yellow, or other colours.

" + } +}, +{ + "pk": 23, + "model": "demosite.standardpage", + "fields": { + "body": "

The origin of the genus appears to be in the general area of Eastern Siberia/Mongolia. Wagtails spread rapidly across Eurasia and dispersed to Africa in the Zanclean (Early Pliocene) where the sub-Saharan lineage was later isolated. The African Pied Wagtail (and possibly the Mekong Wagtail) diverged prior to the massive radiation of the white-bellied black-throated and most yellow-bellied forms, all of which took place during the late Piacenzian (early Late Pliocene), c. 3 mya.


Three species are poly- or paraphyletic in the present taxonomical arrangement and either subspecies need to be reassigned and/or species split up. The Blue-headed Wagtail (AKA Yellow Wagtail and many other names), especially, has always been a taxonomical nightmare with over a dozen currently accepted subspecies and many more invalid ones. The two remaining \"monochrome\" species, Mekong and African Pied Wagtail may be closely related, or a most striking example of convergent evolution.

", + "feed_image": null, + "intro": "

The origin of the genus appears to be in the general area of Eastern Siberia/Mongolia. Wagtails spread rapidly across Eurasia and dispersed to Africa in the Zanclean (Early Pliocene) where the sub-Saharan lineage was later isolated. The African Pied Wagtail (and possibly the Mekong Wagtail) diverged prior to the massive radiation of the white-bellied black-throated and most yellow-bellied forms, all of which took place during the late Piacenzian (early Late Pliocene), c. 3 mya.

" + } +}, +{ + "pk": 1, + "model": "demosite.standardpagecarouselitem", + "fields": { + "link_page": null, + "embed_url": "", + "image": 13, + "link_external": "http://www.flickr.com/photos/ruthhb/", + "caption": "Hopalong wagtail by Ruth Flickr", + "sort_order": 0, + "link_document": null, + "page": 10 + } +}, +{ + "pk": 2, + "model": "demosite.standardpagecarouselitem", + "fields": { + "link_page": null, + "embed_url": "", + "image": 15, + "link_external": "http://www.flickr.com/photos/lipkee/", + "caption": "Grey wagtail by Lip Kee", + "sort_order": 1, + "link_document": null, + "page": 10 + } +}, +{ + "pk": 1, + "model": "demosite.standardpagerelatedlink", + "fields": { + "link_page": 4, + "title": "Internal link to events", + "link_external": "", + "sort_order": 0, + "link_document": null, + "page": 10 + } +}, +{ + "pk": 2, + "model": "demosite.standardpagerelatedlink", + "fields": { + "link_page": null, + "title": "External link to google", + "link_external": "http://www.google.com/", + "sort_order": 1, + "link_document": null, + "page": 10 + } +}, +{ + "pk": 1, + "model": "taggit.tag", + "fields": { + "name": "writers", + "slug": "writers" + } +}, +{ + "pk": 2, + "model": "taggit.tag", + "fields": { + "name": "people", + "slug": "people" + } +}, +{ + "pk": 3, + "model": "taggit.tag", + "fields": { + "name": "person", + "slug": "person" + } +}, +{ + "pk": 4, + "model": "taggit.tag", + "fields": { + "name": "wagtail", + "slug": "wagtail" + } +}, +{ + "pk": 5, + "model": "taggit.tag", + "fields": { + "name": "bird", + "slug": "bird" + } +}, +{ + "pk": 6, + "model": "taggit.tag", + "fields": { + "name": "writer", + "slug": "writer" + } +}, +{ + "pk": 1, + "model": "wagtaildocs.document", + "fields": { + "title": "Wagtail by mark Harkin", + "created_at": "2014-02-06T10:14:47.173Z", + "file": "original_images/wagtail_by_markyharky.jpg", + "uploaded_by_user": null + } +}, +{ + "pk": 2, + "model": "wagtaildocs.document", + "fields": { + "title": "James Joyce", + "created_at": "2014-02-06T10:37:10.518Z", + "file": "original_images/James_Joyce_in_1915.jpg", + "uploaded_by_user": null + } +}, +{ + "pk": 3, + "model": "wagtaildocs.document", + "fields": { + "title": "David Mitchell", + "created_at": "2014-02-06T10:42:46.536Z", + "file": "original_images/David_Mitchell_by_Kubik.JPG", + "uploaded_by_user": null + } +}, +{ + "pk": 4, + "model": "wagtaildocs.document", + "fields": { + "title": "Wagtail by joe Buckingham", + "created_at": "2014-02-06T10:49:29.579Z", + "file": "original_images/wagtail_by_joe_buckingham.jpg", + "uploaded_by_user": null + } +}, +{ + "pk": 5, + "model": "wagtaildocs.document", + "fields": { + "title": "Wagtail by fs-phil", + "created_at": "2014-02-06T10:54:29.963Z", + "file": "original_images/wagtail_by_fs-phil.jpg", + "uploaded_by_user": null + } +}, +{ + "pk": 6, + "model": "wagtaildocs.document", + "fields": { + "title": "White wagtail by Koshy Koshy", + "created_at": "2014-02-06T10:57:05.536Z", + "file": "original_images/white_wagtail_by_Koshyk.jpg", + "uploaded_by_user": null + } +}, +{ + "pk": 7, + "model": "wagtaildocs.document", + "fields": { + "title": "Pied wagtail by Marie Hale", + "created_at": "2014-02-06T11:05:12.370Z", + "file": "original_images/pied_wagtail_by_Marie_Hale.jpg", + "uploaded_by_user": null + } +}, +{ + "pk": 8, + "model": "wagtaildocs.document", + "fields": { + "title": "Wagtail at Borovoye, Kazakhstan by Ken and Nyetta", + "created_at": "2014-02-06T11:08:09.355Z", + "file": "original_images/wagtail_at_Borovoye_Kazakhstan_by_Ken_and_Nyetta.jpg", + "uploaded_by_user": null + } +}, +{ + "pk": 9, + "model": "wagtaildocs.document", + "fields": { + "title": "Wagtail sproing by Jim Bendon", + "created_at": "2014-02-06T11:10:01.185Z", + "file": "original_images/wagtail_sproing_by_Jim_Bendon.jpg", + "uploaded_by_user": null + } +}, +{ + "pk": 10, + "model": "wagtaildocs.document", + "fields": { + "title": "Hopalong wagtail by Ruth Flickr", + "created_at": "2014-02-06T11:15:32.454Z", + "file": "original_images/hopalong_wagtail_by_Ruth_Flickr.jpg", + "uploaded_by_user": null + } +}, +{ + "pk": 11, + "model": "wagtaildocs.document", + "fields": { + "title": "Wagtail collects insects by Margrit", + "created_at": "2014-02-06T11:21:13.596Z", + "file": "original_images/wagtail_collects_insects_by_Maggi_94.jpg", + "uploaded_by_user": null + } +}, +{ + "pk": 12, + "model": "wagtaildocs.document", + "fields": { + "title": "Grey wagtail by Lip Kee", + "created_at": "2014-02-06T11:23:36.409Z", + "file": "original_images/grey_wagtail_by_lip_kee.jpg", + "uploaded_by_user": null + } +} +] diff --git a/wagtail/tests/demosite/migrations/0001_initial.py b/wagtail/tests/demosite/migrations/0001_initial.py new file mode 100644 index 000000000..a7eb7c757 --- /dev/null +++ b/wagtail/tests/demosite/migrations/0001_initial.py @@ -0,0 +1,513 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations +import django.db.models.deletion +import modelcluster.tags +import wagtail.wagtailcore.fields +import modelcluster.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('wagtailimages', '0005_make_filter_spec_unique'), + ('taggit', '0001_initial'), + ('wagtaildocs', '0002_initial_data'), + ('wagtailcore', '0013_update_golive_expire_help_text'), + ] + + operations = [ + migrations.CreateModel( + name='BlogEntryPage', + fields=[ + ('page_ptr', models.OneToOneField(to='wagtailcore.Page', serialize=False, parent_link=True, related_name='+', primary_key=True)), + ('body', wagtail.wagtailcore.fields.RichTextField()), + ('date', models.DateField(verbose_name='Post date')), + ('feed_image', models.ForeignKey(to='wagtailimages.Image', blank=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', null=True)), + ], + options={ + 'abstract': False, + }, + bases=('wagtailcore.page',), + ), + migrations.CreateModel( + name='BlogEntryPageCarouselItem', + fields=[ + ('id', models.AutoField(serialize=False, verbose_name='ID', primary_key=True, auto_created=True)), + ('sort_order', models.IntegerField(null=True, editable=False, blank=True)), + ('link_external', models.URLField(blank=True, verbose_name='External link')), + ('embed_url', models.URLField(blank=True, verbose_name='Embed URL')), + ('caption', models.CharField(blank=True, max_length=255)), + ('image', models.ForeignKey(to='wagtailimages.Image', blank=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', null=True)), + ('link_document', models.ForeignKey(to='wagtaildocs.Document', blank=True, related_name='+', null=True)), + ], + options={ + 'ordering': ['sort_order'], + 'abstract': False, + }, + bases=(models.Model,), + ), + migrations.CreateModel( + name='BlogEntryPageRelatedLink', + fields=[ + ('id', models.AutoField(serialize=False, verbose_name='ID', primary_key=True, auto_created=True)), + ('sort_order', models.IntegerField(null=True, editable=False, blank=True)), + ('link_external', models.URLField(blank=True, verbose_name='External link')), + ('title', models.CharField(help_text='Link title', max_length=255)), + ('link_document', models.ForeignKey(to='wagtaildocs.Document', blank=True, related_name='+', null=True)), + ], + options={ + 'ordering': ['sort_order'], + 'abstract': False, + }, + bases=(models.Model,), + ), + migrations.CreateModel( + name='BlogEntryPageTag', + fields=[ + ('id', models.AutoField(serialize=False, verbose_name='ID', primary_key=True, auto_created=True)), + ('content_object', modelcluster.fields.ParentalKey(to='demosite.BlogEntryPage', related_name='tagged_items')), + ('tag', models.ForeignKey(to='taggit.Tag', related_name='demosite_blogentrypagetag_items')), + ], + options={ + 'abstract': False, + }, + bases=(models.Model,), + ), + migrations.CreateModel( + name='BlogIndexPage', + fields=[ + ('page_ptr', models.OneToOneField(to='wagtailcore.Page', serialize=False, parent_link=True, related_name='+', primary_key=True)), + ('intro', wagtail.wagtailcore.fields.RichTextField(blank=True)), + ], + options={ + 'abstract': False, + }, + bases=('wagtailcore.page',), + ), + migrations.CreateModel( + name='BlogIndexPageRelatedLink', + fields=[ + ('id', models.AutoField(serialize=False, verbose_name='ID', primary_key=True, auto_created=True)), + ('sort_order', models.IntegerField(null=True, editable=False, blank=True)), + ('link_external', models.URLField(blank=True, verbose_name='External link')), + ('title', models.CharField(help_text='Link title', max_length=255)), + ('link_document', models.ForeignKey(to='wagtaildocs.Document', blank=True, related_name='+', null=True)), + ], + options={ + 'ordering': ['sort_order'], + 'abstract': False, + }, + bases=(models.Model,), + ), + migrations.CreateModel( + name='ContactPage', + fields=[ + ('telephone', models.CharField(blank=True, max_length=20)), + ('email', models.EmailField(blank=True, max_length=75)), + ('address_1', models.CharField(blank=True, max_length=255)), + ('address_2', models.CharField(blank=True, max_length=255)), + ('city', models.CharField(blank=True, max_length=255)), + ('country', models.CharField(blank=True, max_length=255)), + ('post_code', models.CharField(blank=True, max_length=10)), + ('page_ptr', models.OneToOneField(to='wagtailcore.Page', serialize=False, parent_link=True, related_name='+', primary_key=True)), + ('body', wagtail.wagtailcore.fields.RichTextField(blank=True)), + ('feed_image', models.ForeignKey(to='wagtailimages.Image', blank=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', null=True)), + ], + options={ + 'abstract': False, + }, + bases=('wagtailcore.page', models.Model), + ), + migrations.CreateModel( + name='EventIndexPage', + fields=[ + ('page_ptr', models.OneToOneField(to='wagtailcore.Page', serialize=False, parent_link=True, related_name='+', primary_key=True)), + ('intro', wagtail.wagtailcore.fields.RichTextField(blank=True)), + ], + options={ + 'abstract': False, + }, + bases=('wagtailcore.page',), + ), + migrations.CreateModel( + name='EventIndexPageRelatedLink', + fields=[ + ('id', models.AutoField(serialize=False, verbose_name='ID', primary_key=True, auto_created=True)), + ('sort_order', models.IntegerField(null=True, editable=False, blank=True)), + ('link_external', models.URLField(blank=True, verbose_name='External link')), + ('title', models.CharField(help_text='Link title', max_length=255)), + ('link_document', models.ForeignKey(to='wagtaildocs.Document', blank=True, related_name='+', null=True)), + ], + options={ + 'ordering': ['sort_order'], + 'abstract': False, + }, + bases=(models.Model,), + ), + migrations.CreateModel( + name='EventPage', + fields=[ + ('page_ptr', models.OneToOneField(to='wagtailcore.Page', serialize=False, parent_link=True, related_name='+', primary_key=True)), + ('date_from', models.DateField(verbose_name='Start date')), + ('date_to', models.DateField(help_text='Not required if event is on a single day', null=True, verbose_name='End date', blank=True)), + ('time_from', models.TimeField(null=True, verbose_name='Start time', blank=True)), + ('time_to', models.TimeField(null=True, verbose_name='End time', blank=True)), + ('audience', models.CharField(choices=[('public', 'Public'), ('private', 'Private')], max_length=255)), + ('location', models.CharField(max_length=255)), + ('body', wagtail.wagtailcore.fields.RichTextField(blank=True)), + ('cost', models.CharField(max_length=255)), + ('signup_link', models.URLField(blank=True)), + ('feed_image', models.ForeignKey(to='wagtailimages.Image', blank=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', null=True)), + ], + options={ + 'abstract': False, + }, + bases=('wagtailcore.page',), + ), + migrations.CreateModel( + name='EventPageCarouselItem', + fields=[ + ('id', models.AutoField(serialize=False, verbose_name='ID', primary_key=True, auto_created=True)), + ('sort_order', models.IntegerField(null=True, editable=False, blank=True)), + ('link_external', models.URLField(blank=True, verbose_name='External link')), + ('embed_url', models.URLField(blank=True, verbose_name='Embed URL')), + ('caption', models.CharField(blank=True, max_length=255)), + ('image', models.ForeignKey(to='wagtailimages.Image', blank=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', null=True)), + ('link_document', models.ForeignKey(to='wagtaildocs.Document', blank=True, related_name='+', null=True)), + ], + options={ + 'ordering': ['sort_order'], + 'abstract': False, + }, + bases=(models.Model,), + ), + migrations.CreateModel( + name='EventPageRelatedLink', + fields=[ + ('id', models.AutoField(serialize=False, verbose_name='ID', primary_key=True, auto_created=True)), + ('sort_order', models.IntegerField(null=True, editable=False, blank=True)), + ('link_external', models.URLField(blank=True, verbose_name='External link')), + ('title', models.CharField(help_text='Link title', max_length=255)), + ('link_document', models.ForeignKey(to='wagtaildocs.Document', blank=True, related_name='+', null=True)), + ], + options={ + 'ordering': ['sort_order'], + 'abstract': False, + }, + bases=(models.Model,), + ), + migrations.CreateModel( + name='EventPageSpeaker', + fields=[ + ('id', models.AutoField(serialize=False, verbose_name='ID', primary_key=True, auto_created=True)), + ('sort_order', models.IntegerField(null=True, editable=False, blank=True)), + ('link_external', models.URLField(blank=True, verbose_name='External link')), + ('first_name', models.CharField(blank=True, verbose_name='Name', max_length=255)), + ('last_name', models.CharField(blank=True, verbose_name='Surname', max_length=255)), + ('image', models.ForeignKey(to='wagtailimages.Image', blank=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', null=True)), + ('link_document', models.ForeignKey(to='wagtaildocs.Document', blank=True, related_name='+', null=True)), + ], + options={ + 'ordering': ['sort_order'], + 'abstract': False, + }, + bases=(models.Model,), + ), + migrations.CreateModel( + name='HomePage', + fields=[ + ('page_ptr', models.OneToOneField(to='wagtailcore.Page', serialize=False, parent_link=True, related_name='+', primary_key=True)), + ('body', wagtail.wagtailcore.fields.RichTextField(blank=True)), + ], + options={ + 'verbose_name': 'Homepage', + }, + bases=('wagtailcore.page',), + ), + migrations.CreateModel( + name='HomePageCarouselItem', + fields=[ + ('id', models.AutoField(serialize=False, verbose_name='ID', primary_key=True, auto_created=True)), + ('sort_order', models.IntegerField(null=True, editable=False, blank=True)), + ('link_external', models.URLField(blank=True, verbose_name='External link')), + ('embed_url', models.URLField(blank=True, verbose_name='Embed URL')), + ('caption', models.CharField(blank=True, max_length=255)), + ('image', models.ForeignKey(to='wagtailimages.Image', blank=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', null=True)), + ('link_document', models.ForeignKey(to='wagtaildocs.Document', blank=True, related_name='+', null=True)), + ], + options={ + 'ordering': ['sort_order'], + 'abstract': False, + }, + bases=(models.Model,), + ), + migrations.CreateModel( + name='HomePageRelatedLink', + fields=[ + ('id', models.AutoField(serialize=False, verbose_name='ID', primary_key=True, auto_created=True)), + ('sort_order', models.IntegerField(null=True, editable=False, blank=True)), + ('link_external', models.URLField(blank=True, verbose_name='External link')), + ('title', models.CharField(help_text='Link title', max_length=255)), + ('link_document', models.ForeignKey(to='wagtaildocs.Document', blank=True, related_name='+', null=True)), + ], + options={ + 'ordering': ['sort_order'], + 'abstract': False, + }, + bases=(models.Model,), + ), + migrations.CreateModel( + name='PersonPage', + fields=[ + ('telephone', models.CharField(blank=True, max_length=20)), + ('email', models.EmailField(blank=True, max_length=75)), + ('address_1', models.CharField(blank=True, max_length=255)), + ('address_2', models.CharField(blank=True, max_length=255)), + ('city', models.CharField(blank=True, max_length=255)), + ('country', models.CharField(blank=True, max_length=255)), + ('post_code', models.CharField(blank=True, max_length=10)), + ('page_ptr', models.OneToOneField(to='wagtailcore.Page', serialize=False, parent_link=True, related_name='+', primary_key=True)), + ('first_name', models.CharField(max_length=255)), + ('last_name', models.CharField(max_length=255)), + ('intro', wagtail.wagtailcore.fields.RichTextField(blank=True)), + ('biography', wagtail.wagtailcore.fields.RichTextField(blank=True)), + ('feed_image', models.ForeignKey(to='wagtailimages.Image', blank=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', null=True)), + ('image', models.ForeignKey(to='wagtailimages.Image', blank=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', null=True)), + ], + options={ + 'abstract': False, + }, + bases=('wagtailcore.page', models.Model), + ), + migrations.CreateModel( + name='PersonPageRelatedLink', + fields=[ + ('id', models.AutoField(serialize=False, verbose_name='ID', primary_key=True, auto_created=True)), + ('sort_order', models.IntegerField(null=True, editable=False, blank=True)), + ('link_external', models.URLField(blank=True, verbose_name='External link')), + ('title', models.CharField(help_text='Link title', max_length=255)), + ('link_document', models.ForeignKey(to='wagtaildocs.Document', blank=True, related_name='+', null=True)), + ], + options={ + 'ordering': ['sort_order'], + 'abstract': False, + }, + bases=(models.Model,), + ), + migrations.CreateModel( + name='StandardIndexPage', + fields=[ + ('page_ptr', models.OneToOneField(to='wagtailcore.Page', serialize=False, parent_link=True, related_name='+', primary_key=True)), + ('intro', wagtail.wagtailcore.fields.RichTextField(blank=True)), + ('feed_image', models.ForeignKey(to='wagtailimages.Image', blank=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', null=True)), + ], + options={ + 'abstract': False, + }, + bases=('wagtailcore.page',), + ), + migrations.CreateModel( + name='StandardIndexPageRelatedLink', + fields=[ + ('id', models.AutoField(serialize=False, verbose_name='ID', primary_key=True, auto_created=True)), + ('sort_order', models.IntegerField(null=True, editable=False, blank=True)), + ('link_external', models.URLField(blank=True, verbose_name='External link')), + ('title', models.CharField(help_text='Link title', max_length=255)), + ('link_document', models.ForeignKey(to='wagtaildocs.Document', blank=True, related_name='+', null=True)), + ], + options={ + 'ordering': ['sort_order'], + 'abstract': False, + }, + bases=(models.Model,), + ), + migrations.CreateModel( + name='StandardPage', + fields=[ + ('page_ptr', models.OneToOneField(to='wagtailcore.Page', serialize=False, parent_link=True, related_name='+', primary_key=True)), + ('intro', wagtail.wagtailcore.fields.RichTextField(blank=True)), + ('body', wagtail.wagtailcore.fields.RichTextField(blank=True)), + ('feed_image', models.ForeignKey(to='wagtailimages.Image', blank=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', null=True)), + ], + options={ + 'abstract': False, + }, + bases=('wagtailcore.page',), + ), + migrations.CreateModel( + name='StandardPageCarouselItem', + fields=[ + ('id', models.AutoField(serialize=False, verbose_name='ID', primary_key=True, auto_created=True)), + ('sort_order', models.IntegerField(null=True, editable=False, blank=True)), + ('link_external', models.URLField(blank=True, verbose_name='External link')), + ('embed_url', models.URLField(blank=True, verbose_name='Embed URL')), + ('caption', models.CharField(blank=True, max_length=255)), + ('image', models.ForeignKey(to='wagtailimages.Image', blank=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', null=True)), + ('link_document', models.ForeignKey(to='wagtaildocs.Document', blank=True, related_name='+', null=True)), + ('link_page', models.ForeignKey(to='wagtailcore.Page', blank=True, related_name='+', null=True)), + ('page', modelcluster.fields.ParentalKey(to='demosite.StandardPage', related_name='carousel_items')), + ], + options={ + 'ordering': ['sort_order'], + 'abstract': False, + }, + bases=(models.Model,), + ), + migrations.CreateModel( + name='StandardPageRelatedLink', + fields=[ + ('id', models.AutoField(serialize=False, verbose_name='ID', primary_key=True, auto_created=True)), + ('sort_order', models.IntegerField(null=True, editable=False, blank=True)), + ('link_external', models.URLField(blank=True, verbose_name='External link')), + ('title', models.CharField(help_text='Link title', max_length=255)), + ('link_document', models.ForeignKey(to='wagtaildocs.Document', blank=True, related_name='+', null=True)), + ('link_page', models.ForeignKey(to='wagtailcore.Page', blank=True, related_name='+', null=True)), + ('page', modelcluster.fields.ParentalKey(to='demosite.StandardPage', related_name='related_links')), + ], + options={ + 'ordering': ['sort_order'], + 'abstract': False, + }, + bases=(models.Model,), + ), + migrations.AddField( + model_name='standardindexpagerelatedlink', + name='link_page', + field=models.ForeignKey(to='wagtailcore.Page', blank=True, related_name='+', null=True), + preserve_default=True, + ), + migrations.AddField( + model_name='standardindexpagerelatedlink', + name='page', + field=modelcluster.fields.ParentalKey(to='demosite.StandardIndexPage', related_name='related_links'), + preserve_default=True, + ), + migrations.AddField( + model_name='personpagerelatedlink', + name='link_page', + field=models.ForeignKey(to='wagtailcore.Page', blank=True, related_name='+', null=True), + preserve_default=True, + ), + migrations.AddField( + model_name='personpagerelatedlink', + name='page', + field=modelcluster.fields.ParentalKey(to='demosite.PersonPage', related_name='related_links'), + preserve_default=True, + ), + migrations.AddField( + model_name='homepagerelatedlink', + name='link_page', + field=models.ForeignKey(to='wagtailcore.Page', blank=True, related_name='+', null=True), + preserve_default=True, + ), + migrations.AddField( + model_name='homepagerelatedlink', + name='page', + field=modelcluster.fields.ParentalKey(to='demosite.HomePage', related_name='related_links'), + preserve_default=True, + ), + migrations.AddField( + model_name='homepagecarouselitem', + name='link_page', + field=models.ForeignKey(to='wagtailcore.Page', blank=True, related_name='+', null=True), + preserve_default=True, + ), + migrations.AddField( + model_name='homepagecarouselitem', + name='page', + field=modelcluster.fields.ParentalKey(to='demosite.HomePage', related_name='carousel_items'), + preserve_default=True, + ), + migrations.AddField( + model_name='eventpagespeaker', + name='link_page', + field=models.ForeignKey(to='wagtailcore.Page', blank=True, related_name='+', null=True), + preserve_default=True, + ), + migrations.AddField( + model_name='eventpagespeaker', + name='page', + field=modelcluster.fields.ParentalKey(to='demosite.EventPage', related_name='speakers'), + preserve_default=True, + ), + migrations.AddField( + model_name='eventpagerelatedlink', + name='link_page', + field=models.ForeignKey(to='wagtailcore.Page', blank=True, related_name='+', null=True), + preserve_default=True, + ), + migrations.AddField( + model_name='eventpagerelatedlink', + name='page', + field=modelcluster.fields.ParentalKey(to='demosite.EventPage', related_name='related_links'), + preserve_default=True, + ), + migrations.AddField( + model_name='eventpagecarouselitem', + name='link_page', + field=models.ForeignKey(to='wagtailcore.Page', blank=True, related_name='+', null=True), + preserve_default=True, + ), + migrations.AddField( + model_name='eventpagecarouselitem', + name='page', + field=modelcluster.fields.ParentalKey(to='demosite.EventPage', related_name='carousel_items'), + preserve_default=True, + ), + migrations.AddField( + model_name='eventindexpagerelatedlink', + name='link_page', + field=models.ForeignKey(to='wagtailcore.Page', blank=True, related_name='+', null=True), + preserve_default=True, + ), + migrations.AddField( + model_name='eventindexpagerelatedlink', + name='page', + field=modelcluster.fields.ParentalKey(to='demosite.EventIndexPage', related_name='related_links'), + preserve_default=True, + ), + migrations.AddField( + model_name='blogindexpagerelatedlink', + name='link_page', + field=models.ForeignKey(to='wagtailcore.Page', blank=True, related_name='+', null=True), + preserve_default=True, + ), + migrations.AddField( + model_name='blogindexpagerelatedlink', + name='page', + field=modelcluster.fields.ParentalKey(to='demosite.BlogIndexPage', related_name='related_links'), + preserve_default=True, + ), + migrations.AddField( + model_name='blogentrypagerelatedlink', + name='link_page', + field=models.ForeignKey(to='wagtailcore.Page', blank=True, related_name='+', null=True), + preserve_default=True, + ), + migrations.AddField( + model_name='blogentrypagerelatedlink', + name='page', + field=modelcluster.fields.ParentalKey(to='demosite.BlogEntryPage', related_name='related_links'), + preserve_default=True, + ), + migrations.AddField( + model_name='blogentrypagecarouselitem', + name='link_page', + field=models.ForeignKey(to='wagtailcore.Page', blank=True, related_name='+', null=True), + preserve_default=True, + ), + migrations.AddField( + model_name='blogentrypagecarouselitem', + name='page', + field=modelcluster.fields.ParentalKey(to='demosite.BlogEntryPage', related_name='carousel_items'), + preserve_default=True, + ), + migrations.AddField( + model_name='blogentrypage', + name='tags', + field=modelcluster.tags.ClusterTaggableManager(help_text='A comma-separated list of tags.', through='demosite.BlogEntryPageTag', blank=True, verbose_name='Tags', to='taggit.Tag'), + preserve_default=True, + ), + ] diff --git a/wagtail/tests/demosite/migrations/__init__.py b/wagtail/tests/demosite/migrations/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/wagtail/tests/demosite/models.py b/wagtail/tests/demosite/models.py new file mode 100644 index 000000000..724e61600 --- /dev/null +++ b/wagtail/tests/demosite/models.py @@ -0,0 +1,594 @@ +from django.db import models +from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger + +from modelcluster.fields import ParentalKey +from modelcluster.tags import ClusterTaggableManager +from taggit.models import Tag, TaggedItemBase + +from wagtail.wagtailcore.models import Page, Orderable +from wagtail.wagtailcore.fields import RichTextField +from wagtail.wagtailadmin.edit_handlers import FieldPanel, MultiFieldPanel, \ + InlinePanel, PageChooserPanel +from wagtail.wagtailimages.edit_handlers import ImageChooserPanel +from wagtail.wagtaildocs.edit_handlers import DocumentChooserPanel +from wagtail.wagtailsnippets.models import register_snippet +from wagtail.wagtailforms.models import AbstractEmailForm, AbstractFormField +from wagtail.wagtailsearch import index + + +# ABSTRACT MODELS +# ============================= + +class AbstractLinkFields(models.Model): + link_external = models.URLField("External link", blank=True) + link_page = models.ForeignKey( + 'wagtailcore.Page', + null=True, + blank=True, + related_name='+' + ) + link_document = models.ForeignKey( + 'wagtaildocs.Document', + null=True, + blank=True, + related_name='+' + ) + + @property + def link(self): + if self.link_page: + return self.link_page.url + elif self.link_document: + return self.link_document.url + else: + return self.link_external + + api_fields = ('link', ) + + panels = [ + FieldPanel('link_external'), + PageChooserPanel('link_page'), + DocumentChooserPanel('link_document'), + ] + + class Meta: + abstract = True + + +class AbstractRelatedLink(AbstractLinkFields): + title = models.CharField(max_length=255, help_text="Link title") + + api_fields = ('title', ) + AbstractLinkFields.api_fields + + panels = [ + FieldPanel('title'), + MultiFieldPanel(AbstractLinkFields.panels, "Link"), + ] + + class Meta: + abstract = True + + +class AbstractCarouselItem(AbstractLinkFields): + image = models.ForeignKey( + 'wagtailimages.Image', + null=True, + blank=True, + on_delete=models.SET_NULL, + related_name='+' + ) + embed_url = models.URLField("Embed URL", blank=True) + caption = models.CharField(max_length=255, blank=True) + + api_fields = ( + 'image', + 'embed_url', + 'caption', + ) + AbstractLinkFields.api_fields + + panels = [ + ImageChooserPanel('image'), + FieldPanel('embed_url'), + FieldPanel('caption'), + MultiFieldPanel(AbstractLinkFields.panels, "Link"), + ] + + class Meta: + abstract = True + + +class ContactFieldsMixin(models.Model): + telephone = models.CharField(max_length=20, blank=True) + email = models.EmailField(blank=True) + address_1 = models.CharField(max_length=255, blank=True) + address_2 = models.CharField(max_length=255, blank=True) + city = models.CharField(max_length=255, blank=True) + country = models.CharField(max_length=255, blank=True) + post_code = models.CharField(max_length=10, blank=True) + + api_fields = ( + 'telephone', + 'email', + 'address_1', + 'address_2', + 'city', + 'country', + 'post_code', + ) + + panels = [ + FieldPanel('telephone'), + FieldPanel('email'), + FieldPanel('address_1'), + FieldPanel('address_2'), + FieldPanel('city'), + FieldPanel('country'), + FieldPanel('post_code'), + ] + + class Meta: + abstract = True + + +# PAGE MODELS +# ============================= + +# Home page + +class HomePage(Page): + page_ptr = models.OneToOneField(Page, parent_link=True, related_name='+') + body = RichTextField(blank=True) + + api_fields = ( + 'body', + 'carousel_items', + 'related_links', + ) + + search_fields = Page.search_fields + ( + index.SearchField('body'), + ) + + class Meta: + verbose_name = "Homepage" + + +class HomePageCarouselItem(Orderable, AbstractCarouselItem): + page = ParentalKey('HomePage', related_name='carousel_items') + +class HomePageRelatedLink(Orderable, AbstractRelatedLink): + page = ParentalKey('HomePage', related_name='related_links') + +HomePage.content_panels = Page.content_panels + [ + FieldPanel('body', classname="full"), + + InlinePanel(HomePage, 'carousel_items', label="Carousel items"), + InlinePanel(HomePage, 'related_links', label="Related links"), +] + + +# Standard pages + +class StandardPage(Page): + page_ptr = models.OneToOneField(Page, parent_link=True, related_name='+') + intro = RichTextField(blank=True) + body = RichTextField(blank=True) + feed_image = models.ForeignKey( + 'wagtailimages.Image', + null=True, + blank=True, + on_delete=models.SET_NULL, + related_name='+' + ) + + api_fields = ( + 'intro', + 'body', + 'feed_image', + 'carousel_items', + 'related_links', + ) + + search_fields = Page.search_fields + ( + index.SearchField('intro'), + index.SearchField('body'), + ) + +class StandardPageCarouselItem(Orderable, AbstractCarouselItem): + page = ParentalKey('StandardPage', related_name='carousel_items') + +class StandardPageRelatedLink(Orderable, AbstractRelatedLink): + page = ParentalKey('StandardPage', related_name='related_links') + +StandardPage.content_panels = Page.content_panels + [ + FieldPanel('intro', classname="full"), + InlinePanel(StandardPage, 'carousel_items', label="Carousel items"), + FieldPanel('body', classname="full"), + InlinePanel(StandardPage, 'related_links', label="Related links"), +] + +StandardPage.promote_panels = [ + MultiFieldPanel(Page.promote_panels, "Common page configuration"), + ImageChooserPanel('feed_image'), +] + + +class StandardIndexPage(Page): + page_ptr = models.OneToOneField(Page, parent_link=True, related_name='+') + intro = RichTextField(blank=True) + feed_image = models.ForeignKey( + 'wagtailimages.Image', + null=True, + blank=True, + on_delete=models.SET_NULL, + related_name='+' + ) + + api_fields = ( + 'intro', + 'feed_image', + 'related_links', + ) + + search_fields = Page.search_fields + ( + index.SearchField('intro'), + ) + +class StandardIndexPageRelatedLink(Orderable, AbstractRelatedLink): + page = ParentalKey('StandardIndexPage', related_name='related_links') + +StandardIndexPage.content_panels = Page.content_panels + [ + FieldPanel('intro', classname="full"), + InlinePanel(StandardIndexPage, 'related_links', label="Related links"), +] + +StandardIndexPage.promote_panels = [ + MultiFieldPanel(Page.promote_panels, "Common page configuration"), + ImageChooserPanel('feed_image'), +] + + +# Blog pages + +class BlogEntryPage(Page): + page_ptr = models.OneToOneField(Page, parent_link=True, related_name='+') + body = RichTextField() + tags = ClusterTaggableManager(through='BlogEntryPageTag', blank=True) + date = models.DateField("Post date") + feed_image = models.ForeignKey( + 'wagtailimages.Image', + null=True, + blank=True, + on_delete=models.SET_NULL, + related_name='+' + ) + + api_fields = ( + 'body', + 'tags', + 'date', + 'feed_image', + 'carousel_items', + 'related_links', + ) + + search_fields = Page.search_fields + ( + index.SearchField('body'), + ) + + def get_blog_index(self): + # Find closest ancestor which is a blog index + return BlogIndexPage.ancestor_of(self).last() + +class BlogEntryPageCarouselItem(Orderable, AbstractCarouselItem): + page = ParentalKey('BlogEntryPage', related_name='carousel_items') + +class BlogEntryPageRelatedLink(Orderable, AbstractRelatedLink): + page = ParentalKey('BlogEntryPage', related_name='related_links') + +class BlogEntryPageTag(TaggedItemBase): + content_object = ParentalKey('BlogEntryPage', related_name='tagged_items') + +BlogEntryPage.content_panels = Page.content_panels + [ + FieldPanel('date'), + FieldPanel('body', classname="full"), + InlinePanel(BlogEntryPage, 'carousel_items', label="Carousel items"), + InlinePanel(BlogEntryPage, 'related_links', label="Related links"), +] + +BlogEntryPage.promote_panels = [ + MultiFieldPanel(Page.promote_panels, "Common page configuration"), + ImageChooserPanel('feed_image'), + FieldPanel('tags'), +] + + +class BlogIndexPage(Page): + page_ptr = models.OneToOneField(Page, parent_link=True, related_name='+') + intro = RichTextField(blank=True) + + api_fields = ( + 'intro', + 'related_links', + ) + + search_fields = Page.search_fields + ( + index.SearchField('intro'), + ) + + def get_blog_entries(self): + # Get list of live blog pages that are descendants of this page + entries = BlogEntryPage.objects.descendant_of(self).live() + + # Order by most recent date first + entries = entries.order_by('-date') + + return entries + + def get_context(self, request): + # Get blog entries + entries = self.get_blog_entries() + + # Filter by tag + tag = request.GET.get('tag') + if tag: + entries = entries.filter(tags__name=tag) + + # Pagination + page = request.GET.get('page') + paginator = Paginator(entries, 10) # Show 10 entries per page + try: + entries = paginator.page(page) + except PageNotAnInteger: + entries = paginator.page(1) + except EmptyPage: + entries = paginator.page(paginator.num_pages) + + # Update template context + context = super(BlogIndexPage, self).get_context(request) + context['entries'] = entries + return context + +class BlogIndexPageRelatedLink(Orderable, AbstractRelatedLink): + page = ParentalKey('BlogIndexPage', related_name='related_links') + +BlogIndexPage.content_panels = Page.content_panels + [ + FieldPanel('intro', classname="full"), + InlinePanel(BlogIndexPage, 'related_links', label="Related links"), +] + + +# Events pages + +class EventPage(Page): + page_ptr = models.OneToOneField(Page, parent_link=True, related_name='+') + AUDIENCE_CHOICES = ( + ('public', "Public"), + ('private', "Private"), + ) + + date_from = models.DateField("Start date") + date_to = models.DateField( + "End date", + null=True, + blank=True, + help_text="Not required if event is on a single day" + ) + time_from = models.TimeField("Start time", null=True, blank=True) + time_to = models.TimeField("End time", null=True, blank=True) + audience = models.CharField(max_length=255, choices=AUDIENCE_CHOICES) + location = models.CharField(max_length=255) + body = RichTextField(blank=True) + cost = models.CharField(max_length=255) + signup_link = models.URLField(blank=True) + feed_image = models.ForeignKey( + 'wagtailimages.Image', + null=True, + blank=True, + on_delete=models.SET_NULL, + related_name='+' + ) + + api_fields = ( + 'date_from', + 'date_to', + 'time_from', + 'time_to', + 'audience', + 'location', + 'body', + 'cost', + 'signup_link', + 'feed_image', + 'carousel_items', + 'related_links', + 'speakers', + ) + + search_fields = Page.search_fields + ( + index.SearchField('get_audience_display'), + index.SearchField('location'), + index.SearchField('body'), + ) + + def get_event_index(self): + # Find closest ancestor which is an event index + return EventIndexPage.objects.ancester_of(self).last() + +class EventPageCarouselItem(Orderable, AbstractCarouselItem): + page = ParentalKey('EventPage', related_name='carousel_items') + +class EventPageRelatedLink(Orderable, AbstractRelatedLink): + page = ParentalKey('EventPage', related_name='related_links') + +class EventPageSpeaker(Orderable, AbstractLinkFields): + page = ParentalKey('EventPage', related_name='speakers') + first_name = models.CharField("Name", max_length=255, blank=True) + last_name = models.CharField("Surname", max_length=255, blank=True) + image = models.ForeignKey( + 'wagtailimages.Image', + null=True, + blank=True, + on_delete=models.SET_NULL, + related_name='+' + ) + + api_fields = ( + 'first_name', + 'last_name', + 'image', + ) + + panels = [ + FieldPanel('first_name'), + FieldPanel('last_name'), + ImageChooserPanel('image'), + MultiFieldPanel(AbstractLinkFields.panels, "Link"), + ] + +EventPage.content_panels = Page.content_panels + [ + FieldPanel('date_from'), + FieldPanel('date_to'), + FieldPanel('time_from'), + FieldPanel('time_to'), + FieldPanel('location'), + FieldPanel('audience'), + FieldPanel('cost'), + FieldPanel('signup_link'), + InlinePanel(EventPage, 'carousel_items', label="Carousel items"), + FieldPanel('body', classname="full"), + InlinePanel(EventPage, 'speakers', label="Speakers"), + InlinePanel(EventPage, 'related_links', label="Related links"), +] + +EventPage.promote_panels = [ + MultiFieldPanel(Page.promote_panels, "Common page configuration"), + ImageChooserPanel('feed_image'), +] + + +class EventIndexPage(Page): + page_ptr = models.OneToOneField(Page, parent_link=True, related_name='+') + intro = RichTextField(blank=True) + + api_fields = ( + 'intro', + 'related_links', + ) + + search_fields = Page.search_fields + ( + index.SearchField('intro'), + ) + + def get_events(self): + # Get list of live event pages that are descendants of this page + events = EventPage.objects.descendant_of(self).live() + + # Filter events list to get ones that are either + # running now or start in the future + events = events.filter(date_from__gte=date.today()) + + # Order by date + events = events.order_by('date_from') + + return events + +class EventIndexPageRelatedLink(Orderable, AbstractRelatedLink): + page = ParentalKey('EventIndexPage', related_name='related_links') + +EventIndexPage.content_panels = Page.content_panels + [ + FieldPanel('intro', classname="full"), + InlinePanel(EventIndexPage, 'related_links', label="Related links"), +] + + +# Person page + +class PersonPage(Page, ContactFieldsMixin): + page_ptr = models.OneToOneField(Page, parent_link=True, related_name='+') + first_name = models.CharField(max_length=255) + last_name = models.CharField(max_length=255) + intro = RichTextField(blank=True) + biography = RichTextField(blank=True) + image = models.ForeignKey( + 'wagtailimages.Image', + null=True, + blank=True, + on_delete=models.SET_NULL, + related_name='+' + ) + feed_image = models.ForeignKey( + 'wagtailimages.Image', + null=True, + blank=True, + on_delete=models.SET_NULL, + related_name='+' + ) + + api_fields = ( + 'first_name', + 'last_name', + 'intro', + 'biography', + 'image', + 'feed_image', + 'related_links', + ) + ContactFieldsMixin.api_fields + + search_fields = Page.search_fields + ( + index.SearchField('first_name'), + index.SearchField('last_name'), + index.SearchField('intro'), + index.SearchField('biography'), + ) + +class PersonPageRelatedLink(Orderable, AbstractRelatedLink): + page = ParentalKey('PersonPage', related_name='related_links') + +PersonPage.content_panels = Page.content_panels + [ + FieldPanel('first_name'), + FieldPanel('last_name'), + FieldPanel('intro', classname="full"), + FieldPanel('biography', classname="full"), + ImageChooserPanel('image'), + MultiFieldPanel(ContactFieldsMixin.panels, "Contact"), + InlinePanel(PersonPage, 'related_links', label="Related links"), +] + +PersonPage.promote_panels = [ + MultiFieldPanel(Page.promote_panels, "Common page configuration"), + ImageChooserPanel('feed_image'), +] + + +# Contact page + +class ContactPage(Page, ContactFieldsMixin): + page_ptr = models.OneToOneField(Page, parent_link=True, related_name='+') + body = RichTextField(blank=True) + feed_image = models.ForeignKey( + 'wagtailimages.Image', + null=True, + blank=True, + on_delete=models.SET_NULL, + related_name='+' + ) + + api_fields = ( + 'body', + 'feed_image', + ) + ContactFieldsMixin.api_fields + + search_fields = Page.search_fields + ( + index.SearchField('body'), + ) + +ContactPage.content_panels = Page.content_panels + [ + FieldPanel('body', classname="full"), + MultiFieldPanel(ContactFieldsMixin.panels, "Contact"), +] + +ContactPage.promote_panels = [ + MultiFieldPanel(Page.promote_panels, "Common page configuration"), + ImageChooserPanel('feed_image'), +] diff --git a/wagtail/tests/settings.py b/wagtail/tests/settings.py index 50ffb6ffa..92b058af0 100644 --- a/wagtail/tests/settings.py +++ b/wagtail/tests/settings.py @@ -77,6 +77,7 @@ INSTALLED_APPS = ( 'wagtail.contrib.wagtailroutablepage', 'wagtail.contrib.wagtailfrontendcache', 'wagtail.tests.testapp', + 'wagtail.tests.demosite', 'wagtail.tests.customuser', 'wagtail.tests.snippets', 'wagtail.tests.routablepage', From ed3ddcc6c07486abc0b2e1bf13f15576b83096a2 Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Mon, 23 Mar 2015 19:57:34 +0000 Subject: [PATCH 11/27] Replaced models.get_models with apps.get_models --- wagtail/contrib/wagtailfrontendcache/signal_handlers.py | 6 +++--- wagtail/wagtailimages/models.py | 4 ++-- wagtail/wagtailsearch/index.py | 3 ++- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/wagtail/contrib/wagtailfrontendcache/signal_handlers.py b/wagtail/contrib/wagtailfrontendcache/signal_handlers.py index fe673825f..3e5def1c1 100644 --- a/wagtail/contrib/wagtailfrontendcache/signal_handlers.py +++ b/wagtail/contrib/wagtailfrontendcache/signal_handlers.py @@ -1,4 +1,4 @@ -from django.db import models +from django.apps import apps from wagtail.wagtailcore.signals import page_published, page_unpublished @@ -15,8 +15,8 @@ def page_unpublished_signal_handler(instance, **kwargs): def register_signal_handlers(): # Get list of models that are page types - Page = models.get_model('wagtailcore', 'Page') - indexed_models = [model for model in models.get_models() if issubclass(model, Page)] + Page = apps.get_model('wagtailcore', 'Page') + indexed_models = [model for model in apps.get_models() if issubclass(model, Page)] # Loop through list and register signal handlers for each one for model in indexed_models: diff --git a/wagtail/wagtailimages/models.py b/wagtail/wagtailimages/models.py index c1844f131..a54c581d4 100644 --- a/wagtail/wagtailimages/models.py +++ b/wagtail/wagtailimages/models.py @@ -261,7 +261,7 @@ def image_delete(sender, instance, **kwargs): def get_image_model(): from django.conf import settings - from django.db.models import get_model + from django.apps import apps try: app_label, model_name = settings.WAGTAILIMAGES_IMAGE_MODEL.split('.') @@ -270,7 +270,7 @@ def get_image_model(): except ValueError: raise ImproperlyConfigured("WAGTAILIMAGES_IMAGE_MODEL must be of the form 'app_label.model_name'") - image_model = get_model(app_label, model_name) + image_model = apps.get_model(app_label, model_name) if image_model is None: raise ImproperlyConfigured("WAGTAILIMAGES_IMAGE_MODEL refers to model '%s' that has not been installed" % settings.WAGTAILIMAGES_IMAGE_MODEL) return image_model diff --git a/wagtail/wagtailsearch/index.py b/wagtail/wagtailsearch/index.py index fa2f317ce..d7326386a 100644 --- a/wagtail/wagtailsearch/index.py +++ b/wagtail/wagtailsearch/index.py @@ -3,6 +3,7 @@ import warnings from six import string_types from django.db import models +from django.apps import apps class Indexed(object): @@ -74,7 +75,7 @@ class Indexed(object): def get_indexed_models(): return [ - model for model in models.get_models() + model for model in apps.get_models() if issubclass(model, Indexed) and not model._meta.abstract ] From d80a92cfe45907b9f91fd212a3b06fa0b2321364 Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Thu, 26 Mar 2015 11:29:06 +0000 Subject: [PATCH 12/27] Make subpage_urls a property on RoutablePageTest --- wagtail/tests/routablepage/models.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/wagtail/tests/routablepage/models.py b/wagtail/tests/routablepage/models.py index 51aee5b67..0a3c3692c 100644 --- a/wagtail/tests/routablepage/models.py +++ b/wagtail/tests/routablepage/models.py @@ -9,12 +9,14 @@ def routable_page_external_view(request, arg): return HttpResponse("EXTERNAL VIEW: " + arg) class RoutablePageTest(RoutablePage): - subpage_urls = ( - url(r'^$', 'main', name='main'), - url(r'^archive/year/(\d+)/$', 'archive_by_year', name='archive_by_year'), - url(r'^archive/author/(?P.+)/$', 'archive_by_author', name='archive_by_author'), - url(r'^external/(.+)/$', routable_page_external_view, name='external_view') - ) + @property + def subpage_urls(self): + return ( + url(r'^$', self.main, name='main'), + url(r'^archive/year/(\d+)/$', self.archive_by_year, name='archive_by_year'), + url(r'^archive/author/(?P.+)/$', self.archive_by_author, name='archive_by_author'), + url(r'^external/(.+)/$', routable_page_external_view, name='external_view') + ) def archive_by_year(self, request, year): return HttpResponse("ARCHIVE BY YEAR: " + str(year)) From c77eafdd8e3e35e52c43af1e3374e9ded0cb2b14 Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Tue, 31 Mar 2015 10:25:54 +0100 Subject: [PATCH 13/27] Removed celery from production.py No longer required by Wagtail --- .../project_name/settings/production.py | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/wagtail/project_template/project_name/settings/production.py b/wagtail/project_template/project_name/settings/production.py index e9e9e1971..bf20125a9 100644 --- a/wagtail/project_template/project_name/settings/production.py +++ b/wagtail/project_template/project_name/settings/production.py @@ -13,19 +13,6 @@ TEMPLATE_DEBUG = False COMPRESS_OFFLINE = True -# Send notification emails as a background task using Celery, -# to prevent this from blocking web server threads -# (requires the django-celery package): -# http://celery.readthedocs.org/en/latest/configuration.html - -# import djcelery -# -# djcelery.setup_loader() -# -# CELERY_SEND_TASK_ERROR_EMAILS = True -# BROKER_URL = 'redis://' - - # Use Redis as the cache backend for extra performance # (requires the django-redis-cache package): # http://wagtail.readthedocs.org/en/latest/howto/performance.html#cache From 6f8218f23b6438fd562c2b8898fc29b5742b9cf7 Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Tue, 31 Mar 2015 10:29:58 +0100 Subject: [PATCH 14/27] Remove mention of celery from docs --- docs/howto/performance.rst | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/docs/howto/performance.rst b/docs/howto/performance.rst index 924e49d9f..0e1b64f68 100644 --- a/docs/howto/performance.rst +++ b/docs/howto/performance.rst @@ -28,21 +28,6 @@ We recommend `Redis `_ as a fast, persistent cache. Install Re Without a persistent cache, Wagtail will recreate all compressable assets at each server start, e.g. when any files change under ``./manage.py runserver``. -Sending emails in the background using Celery ---------------------------------------------- - -Various actions in the Wagtail admin backend can trigger notification emails - for example, submitting a page for moderation. In Wagtail's default configuration, these are sent as part of the page request/response cycle, which means that web server threads can get tied up for long periods if many emails are being sent. To avoid this, Wagtail can be configured to do this as a background task, using `Celery `_ as a task queue. To install Celery, add ``django-celery`` to your requirements.txt. A sample configuration, using Redis as the queue backend, would look like:: - - import djcelery - - djcelery.setup_loader() - - CELERY_SEND_TASK_ERROR_EMAILS = True - BROKER_URL = 'redis://' - -See the Celery documentation for instructions on running the worker process in development or production. - - Search ------ From f077fb026dfbd4386226ba2550cffa04e801421d Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Tue, 31 Mar 2015 10:30:59 +0100 Subject: [PATCH 15/27] Remove celery from project_template/requirements.txt --- wagtail/project_template/requirements.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/wagtail/project_template/requirements.txt b/wagtail/project_template/requirements.txt index cccb37a38..a2ad30e9b 100644 --- a/wagtail/project_template/requirements.txt +++ b/wagtail/project_template/requirements.txt @@ -8,4 +8,3 @@ wagtail==1.0b1 # Recommended components to improve performance in production: # django-redis==3.8.2 -# django-celery==3.1.10 From d2bd3ebaef629efe9e46a0d10b178e552f4d6f9e Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Tue, 31 Mar 2015 14:37:56 +0100 Subject: [PATCH 16/27] Changelog/release note for #1120 --- CHANGELOG.txt | 1 + docs/releases/1.0.rst | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 7bfe3c294..cbc86355d 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -39,6 +39,7 @@ Changelog * Date / time pickers now consistently use times without seconds, to prevent Javascript behaviour glitches when focusing / unfocusing fields * Added hooks `register_rich_text_embed_handler` and `register_rich_text_link_handler` for customising link / embed handling within rich text fields * Added hook `construct_homepage_summary_items` for customising the site summary panel on the admin homepage + * No longer automatically tries to use Celery for sending notification emails 0.8.6 (10.03.2015) diff --git a/docs/releases/1.0.rst b/docs/releases/1.0.rst index ce96925c8..3f6c69685 100644 --- a/docs/releases/1.0.rst +++ b/docs/releases/1.0.rst @@ -85,6 +85,7 @@ Project template * The Vagrantfile now listens on port 8000 * Removed ``LOGIN_URL`` and ``LOGIN_REDIRECT_URL`` settings (as Wagtail no longer requires these) + * Removed example Celery configuration from ``production.py`` and ``requirements.txt`` Search @@ -123,6 +124,17 @@ It is no longer necessary to pass the base model as a parameter, so this declara The old format is now deprecated; all existing ``InlinePanel`` declarations should be updated to the new format. +Celery no longer automatically used for sending notification emails +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Previously, Wagtail would try to use Celery whenever the ``djcelery`` module was +installed, even if Celery wasn't actually set up. This could cause a very hard +to track down problem where notification emails would not be sent so this +functionality has now been removed. + +If you would like to keep using Celery for sending notification emails, have a +look at: `django-celery-email `_ + You no longer need ``LOGIN_URL`` and ``LOGIN_REDIRECT_URL`` to point to Wagtail admin. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From a1ccb1504bf7de10b5183c73bf13bafae664e438 Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Tue, 31 Mar 2015 15:15:18 +0100 Subject: [PATCH 17/27] Fix typo in code example. Fixes #1129 Thanks to @negletios for spotting --- docs/pages/streamfield.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/pages/streamfield.rst b/docs/pages/streamfield.rst index 2b8a03bdf..5ea861637 100644 --- a/docs/pages/streamfield.rst +++ b/docs/pages/streamfield.rst @@ -285,10 +285,10 @@ Any block type is valid as the sub-block type, including structural types: .. code-block:: python - ('ingredients_list', blocks.ListBlock(blocks.StructBlock( + ('ingredients_list', blocks.ListBlock(blocks.StructBlock([ ('ingredient', blocks.CharBlock(required=True)), ('amount', blocks.CharBlock()), - ))) + ]))) StreamBlock From 2837af4fbff47a930432f182f2f9c6e211c14f51 Mon Sep 17 00:00:00 2001 From: Eric Drechsel Date: Fri, 21 Nov 2014 11:57:32 -0800 Subject: [PATCH 18/27] Use a common base template for test pages --- wagtail/tests/templates/tests/base.html | 10 ++++++++ .../testapp/templates/tests/event_index.html | 15 ++++------- .../testapp/templates/tests/event_page.html | 25 ++++++++----------- .../tests/event_page_password_required.html | 25 ++++++++----------- .../testapp/templates/tests/form_page.html | 22 ++++++---------- .../templates/tests/form_page_landing.html | 15 +++-------- .../testapp/templates/tests/simple_page.html | 15 +++-------- 7 files changed, 51 insertions(+), 76 deletions(-) create mode 100644 wagtail/tests/templates/tests/base.html diff --git a/wagtail/tests/templates/tests/base.html b/wagtail/tests/templates/tests/base.html new file mode 100644 index 000000000..875d13d9c --- /dev/null +++ b/wagtail/tests/templates/tests/base.html @@ -0,0 +1,10 @@ + + + + {% block html_title %}{{ self.title }}{% endblock %} + + +

{{ self.title }}

+ {% block content %}{% endblock %} + + diff --git a/wagtail/tests/testapp/templates/tests/event_index.html b/wagtail/tests/testapp/templates/tests/event_index.html index dc07020b2..345aac9e0 100644 --- a/wagtail/tests/testapp/templates/tests/event_index.html +++ b/wagtail/tests/testapp/templates/tests/event_index.html @@ -1,10 +1,5 @@ - - - - {{ self.title }} - - -

{{ self.title }}

- {% include "tests/includes/event_listing.html" %} - - +{% extends "tests/base.html" %} + +{% block content %} + {% include "tests/includes/event_listing.html" %} +{% endblock %} diff --git a/wagtail/tests/testapp/templates/tests/event_page.html b/wagtail/tests/testapp/templates/tests/event_page.html index a3ccaa718..f2f486962 100644 --- a/wagtail/tests/testapp/templates/tests/event_page.html +++ b/wagtail/tests/testapp/templates/tests/event_page.html @@ -1,17 +1,12 @@ +{% extends "tests/base.html" %} {% load wagtailcore_tags wagtailimages_tags %} - - - - Event: {{ self.title }} - - -

{{ self.title }}

-

Event

- {% if self.feed_image %} - {% image self.feed_image width-200 class="feed-image" %} - {% endif %} - {{ self.body|richtext }} -

Back to events index

- - +{% block html_title %}Event: {{ self.title }}{% endblock %} +{% block content %} +

Event

+ {% if self.feed_image %} + {% image self.feed_image width-200 class="feed-image" %} + {% endif %} + {{ self.body|richtext }} +

Back to events index

+{% endblock %} diff --git a/wagtail/tests/testapp/templates/tests/event_page_password_required.html b/wagtail/tests/testapp/templates/tests/event_page_password_required.html index e58d740ad..7311c7940 100644 --- a/wagtail/tests/testapp/templates/tests/event_page_password_required.html +++ b/wagtail/tests/testapp/templates/tests/event_page_password_required.html @@ -1,15 +1,10 @@ - - - - {{ self.title }} - - -

{{ self.title }}

-

This event is invitation only. Please enter your password to see the details.

-
- {% csrf_token %} - {{ form.as_p }} - -
- - +{% extends "tests/base.html" %} + +{% block content %} +

This event is invitation only. Please enter your password to see the details.

+
+ {% csrf_token %} + {{ form.as_p }} + +
+{% endblock %} diff --git a/wagtail/tests/testapp/templates/tests/form_page.html b/wagtail/tests/testapp/templates/tests/form_page.html index d908c60a2..f275ec80f 100644 --- a/wagtail/tests/testapp/templates/tests/form_page.html +++ b/wagtail/tests/testapp/templates/tests/form_page.html @@ -1,16 +1,10 @@ +{% extends "tests/base.html" %} {% load wagtailcore_tags %} - - - - {{ self.title }} - - -

{{ self.title }}

-
- {% csrf_token %} - {{ form.as_p }} - -
- - +{% block content %} +
+ {% csrf_token %} + {{ form.as_p }} + +
+{% endblock %} diff --git a/wagtail/tests/testapp/templates/tests/form_page_landing.html b/wagtail/tests/testapp/templates/tests/form_page_landing.html index d9a6369d4..9615c79d3 100644 --- a/wagtail/tests/testapp/templates/tests/form_page_landing.html +++ b/wagtail/tests/testapp/templates/tests/form_page_landing.html @@ -1,12 +1,5 @@ -{% load wagtailcore_tags %} +{% extends "tests/base.html" %} - - - - {{ self.title }} - - -

{{ self.title }}

-

Thank you for your feedback.

- - +{% block content %} +

Thank you for your feedback.

+{% endblock %} diff --git a/wagtail/tests/testapp/templates/tests/simple_page.html b/wagtail/tests/testapp/templates/tests/simple_page.html index 1f3593514..7a173c096 100644 --- a/wagtail/tests/testapp/templates/tests/simple_page.html +++ b/wagtail/tests/testapp/templates/tests/simple_page.html @@ -1,12 +1,5 @@ -{% load wagtailcore_tags %} +{% extends "tests/base.html" %} - - - - {{ self.title }} - - -

{{ self.title }}

-

Simple page

- - +{% block content %} +

Simple page

+{% endblock %} From 8dfa5942da20436233a34aa9a063f855afd410d7 Mon Sep 17 00:00:00 2001 From: Matt Westcott Date: Fri, 24 Oct 2014 12:20:02 +0100 Subject: [PATCH 19/27] Add wagtailuserbar tag to base test template --- wagtail/tests/templates/tests/base.html | 3 +++ 1 file changed, 3 insertions(+) diff --git a/wagtail/tests/templates/tests/base.html b/wagtail/tests/templates/tests/base.html index 875d13d9c..636b5c588 100644 --- a/wagtail/tests/templates/tests/base.html +++ b/wagtail/tests/templates/tests/base.html @@ -1,9 +1,12 @@ +{% load wagtailuserbar %} + {% block html_title %}{{ self.title }}{% endblock %} + {% wagtailuserbar %}

{{ self.title }}

{% block content %}{% endblock %} From a5940bef98be498a5c45fa9a383cb440a7ac0ed2 Mon Sep 17 00:00:00 2001 From: Matt Westcott Date: Fri, 24 Oct 2014 12:41:28 +0100 Subject: [PATCH 20/27] add (partly failing) unit tests for add button on wagtailuserbar --- .../tests/templates/tests/business_child.html | 5 +++ wagtail/wagtailadmin/tests/test_userbar.py | 32 +++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 wagtail/tests/templates/tests/business_child.html diff --git a/wagtail/tests/templates/tests/business_child.html b/wagtail/tests/templates/tests/business_child.html new file mode 100644 index 000000000..33e29f1c2 --- /dev/null +++ b/wagtail/tests/templates/tests/business_child.html @@ -0,0 +1,5 @@ +{% extends "tests/base.html" %} + +{% block content %} +

Business Child

+{% endblock %} diff --git a/wagtail/wagtailadmin/tests/test_userbar.py b/wagtail/wagtailadmin/tests/test_userbar.py index c43a1bbc0..04056f87a 100644 --- a/wagtail/wagtailadmin/tests/test_userbar.py +++ b/wagtail/wagtailadmin/tests/test_userbar.py @@ -7,6 +7,7 @@ from django.contrib.auth.models import AnonymousUser from wagtail.tests.utils import WagtailTestUtils from wagtail.wagtailcore.models import Page +from wagtail.tests.models import BusinessIndex, BusinessChild class TestUserbarTag(TestCase): @@ -60,6 +61,37 @@ class TestUserbarFrontend(TestCase, WagtailTestUtils): self.assertEqual(response.status_code, 403) +class TestUserbarAddLink(TestCase, WagtailTestUtils): + fixtures = ['test.json'] + + def setUp(self): + self.login() + self.homepage = Page.objects.get(url_path='/home/') + self.event_index = Page.objects.get(url_path='/home/events/') + + self.business_index = BusinessIndex(title='Business', slug='business', live=True) + self.homepage.add_child(instance=self.business_index) + + self.business_child = BusinessChild(title='Business Child', slug='child', live=True) + self.business_index.add_child(instance=self.business_child) + + def test_page_allowing_subpages(self): + response = self.client.get(reverse('wagtailadmin_userbar_frontend', args=(self.event_index.id, ))) + + # page allows subpages, so the 'add page' button should add a subpage + expected_url = reverse('wagtailadmin_pages_add_subpage', args=(self.event_index.id, )) + expected_link = 'Add' % expected_url + self.assertContains(response, expected_link) + + def test_page_disallowing_subpages(self): + response = self.client.get(reverse('wagtailadmin_userbar_frontend', args=(self.business_child.id, ))) + print response + # page disallows subpages, so the 'add page' button should add a page at the same level + expected_url = reverse('wagtailadmin_pages_add_subpage', args=(self.business_index.id, )) + expected_link = 'Add' % expected_url + self.assertContains(response, expected_link) + + class TestUserbarModeration(TestCase, WagtailTestUtils): def setUp(self): self.login() From 805e0785562d7080c8c6f828c639432cac18e4a2 Mon Sep 17 00:00:00 2001 From: Eric Drechsel Date: Fri, 21 Nov 2014 13:24:29 -0800 Subject: [PATCH 21/27] test that add button is present only if page allows subpages --- wagtail/wagtailadmin/tests/test_userbar.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/wagtail/wagtailadmin/tests/test_userbar.py b/wagtail/wagtailadmin/tests/test_userbar.py index 04056f87a..4daf9370a 100644 --- a/wagtail/wagtailadmin/tests/test_userbar.py +++ b/wagtail/wagtailadmin/tests/test_userbar.py @@ -78,18 +78,18 @@ class TestUserbarAddLink(TestCase, WagtailTestUtils): def test_page_allowing_subpages(self): response = self.client.get(reverse('wagtailadmin_userbar_frontend', args=(self.event_index.id, ))) - # page allows subpages, so the 'add page' button should add a subpage + # page allows subpages, so the 'add page' button should show expected_url = reverse('wagtailadmin_pages_add_subpage', args=(self.event_index.id, )) expected_link = 'Add' % expected_url self.assertContains(response, expected_link) def test_page_disallowing_subpages(self): response = self.client.get(reverse('wagtailadmin_userbar_frontend', args=(self.business_child.id, ))) - print response - # page disallows subpages, so the 'add page' button should add a page at the same level + + # page disallows subpages, so the 'add page' button shouldn't show expected_url = reverse('wagtailadmin_pages_add_subpage', args=(self.business_index.id, )) - expected_link = 'Add' % expected_url - self.assertContains(response, expected_link) + expected_link = 'Add' % expected_url + self.assertNotContains(response, expected_link) class TestUserbarModeration(TestCase, WagtailTestUtils): From e28051e3f35bcb066c313a1839d9462490bfb478 Mon Sep 17 00:00:00 2001 From: Eric Drechsel Date: Fri, 21 Nov 2014 13:24:57 -0800 Subject: [PATCH 22/27] only include add button in userbar if page allows subpages --- .../templates/wagtailadmin/userbar/item_page_add.html | 4 ++-- wagtail/wagtailadmin/userbar.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/wagtail/wagtailadmin/templates/wagtailadmin/userbar/item_page_add.html b/wagtail/wagtailadmin/templates/wagtailadmin/userbar/item_page_add.html index 45f0002e9..1a4d0a7f4 100644 --- a/wagtail/wagtailadmin/templates/wagtailadmin/userbar/item_page_add.html +++ b/wagtail/wagtailadmin/templates/wagtailadmin/userbar/item_page_add.html @@ -2,5 +2,5 @@ {% load i18n %} {% block item_content %} - {% trans 'Add' %} -{% endblock %} \ No newline at end of file + {% trans 'Add' %} +{% endblock %} diff --git a/wagtail/wagtailadmin/userbar.py b/wagtail/wagtailadmin/userbar.py index 195e936b3..6ee8cda72 100644 --- a/wagtail/wagtailadmin/userbar.py +++ b/wagtail/wagtailadmin/userbar.py @@ -24,7 +24,7 @@ class AddPageItem(BaseItem): return "" # Don't render if user doesn't have ability to add siblings - permission_checker = self.page.get_parent().permissions_for_user(request.user) + permission_checker = self.page.permissions_for_user(request.user) if not permission_checker.can_add_subpage(): return "" From f7ab4048872e61bcbd2c0eefa11bf869901790ec Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Tue, 31 Mar 2015 15:25:43 +0100 Subject: [PATCH 23/27] Comment tweak --- wagtail/wagtailadmin/userbar.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wagtail/wagtailadmin/userbar.py b/wagtail/wagtailadmin/userbar.py index 6ee8cda72..8416255ff 100644 --- a/wagtail/wagtailadmin/userbar.py +++ b/wagtail/wagtailadmin/userbar.py @@ -23,7 +23,7 @@ class AddPageItem(BaseItem): if not request.user.has_perm('wagtailadmin.access_admin'): return "" - # Don't render if user doesn't have ability to add siblings + # Don't render if user doesn't have ability to add children here permission_checker = self.page.permissions_for_user(request.user) if not permission_checker.can_add_subpage(): return "" From addb57c0cdd9268c088771a17584328e508cfa54 Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Tue, 31 Mar 2015 15:29:08 +0100 Subject: [PATCH 24/27] Changelog and release notes for #728 --- CHANGELOG.txt | 1 + docs/releases/1.0.rst | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index cbc86355d..8f9c1ca87 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -40,6 +40,7 @@ Changelog * Added hooks `register_rich_text_embed_handler` and `register_rich_text_link_handler` for customising link / embed handling within rich text fields * Added hook `construct_homepage_summary_items` for customising the site summary panel on the admin homepage * No longer automatically tries to use Celery for sending notification emails + * Added "Add child page" button to admin userbar (Eric Drechsel) 0.8.6 (10.03.2015) diff --git a/docs/releases/1.0.rst b/docs/releases/1.0.rst index 3f6c69685..ccd642f18 100644 --- a/docs/releases/1.0.rst +++ b/docs/releases/1.0.rst @@ -51,6 +51,7 @@ Admin * Added pagination to the snippets listing and chooser * Page / document / image / snippet choosers now include a link to edit the chosen item * Plain text fields in the page editor now use auto-expanding text areas + * Added "Add child page" button to admin userbar **Page editor** From fcdcc3aa7b321db4dd3f22787967cd273aeba2bd Mon Sep 17 00:00:00 2001 From: Yiannis Inglessis Date: Tue, 31 Mar 2015 18:47:10 +0300 Subject: [PATCH 25/27] Fix typo in code example. Fixes #1130 --- docs/pages/streamfield.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/pages/streamfield.rst b/docs/pages/streamfield.rst index 2b8a03bdf..f5250d3dc 100644 --- a/docs/pages/streamfield.rst +++ b/docs/pages/streamfield.rst @@ -305,9 +305,9 @@ A block consisting of a sequence of sub-blocks of different types, which can be ('image', ImageChooserBlock()), ('quotation', blocks.StructBlock([ ('text', blocks.TextBlock()), - ('author', blocks.CharBlock), + ('author', blocks.CharBlock()), ])), - ('video', blocks.EmbedBlock()), + ('video', EmbedBlock()), ], icon='cogs' )) @@ -321,9 +321,9 @@ As with StructBlock, the list of sub-blocks can also be provided as a subclass o image = ImageChooserBlock() quotation = blocks.StructBlock([ ('text', blocks.TextBlock()), - ('author', blocks.CharBlock), + ('author', blocks.CharBlock()), ]) - video = blocks.EmbedBlock + video = EmbedBlock() class Meta: icon='cogs' From 53012e85c273f45c4ed0c634201d08770f315ca1 Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Tue, 31 Mar 2015 17:01:00 +0100 Subject: [PATCH 26/27] Fixed tests --- wagtail/tests/{ => testapp}/templates/tests/base.html | 0 wagtail/tests/{ => testapp}/templates/tests/business_child.html | 0 wagtail/wagtailadmin/tests/test_userbar.py | 2 +- 3 files changed, 1 insertion(+), 1 deletion(-) rename wagtail/tests/{ => testapp}/templates/tests/base.html (100%) rename wagtail/tests/{ => testapp}/templates/tests/business_child.html (100%) diff --git a/wagtail/tests/templates/tests/base.html b/wagtail/tests/testapp/templates/tests/base.html similarity index 100% rename from wagtail/tests/templates/tests/base.html rename to wagtail/tests/testapp/templates/tests/base.html diff --git a/wagtail/tests/templates/tests/business_child.html b/wagtail/tests/testapp/templates/tests/business_child.html similarity index 100% rename from wagtail/tests/templates/tests/business_child.html rename to wagtail/tests/testapp/templates/tests/business_child.html diff --git a/wagtail/wagtailadmin/tests/test_userbar.py b/wagtail/wagtailadmin/tests/test_userbar.py index 4daf9370a..376c91113 100644 --- a/wagtail/wagtailadmin/tests/test_userbar.py +++ b/wagtail/wagtailadmin/tests/test_userbar.py @@ -7,7 +7,7 @@ from django.contrib.auth.models import AnonymousUser from wagtail.tests.utils import WagtailTestUtils from wagtail.wagtailcore.models import Page -from wagtail.tests.models import BusinessIndex, BusinessChild +from wagtail.tests.testapp.models import BusinessIndex, BusinessChild class TestUserbarTag(TestCase): From 996ec4157ea9ebb55f891c6b1efd4bb286d79fec Mon Sep 17 00:00:00 2001 From: Drew Larson Date: Tue, 31 Mar 2015 13:24:09 -0600 Subject: [PATCH 27/27] Support for HTTPS Instagram URLs. --- wagtail/wagtailembeds/oembed_providers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wagtail/wagtailembeds/oembed_providers.py b/wagtail/wagtailembeds/oembed_providers.py index bc944f9bd..30df31b85 100644 --- a/wagtail/wagtailembeds/oembed_providers.py +++ b/wagtail/wagtailembeds/oembed_providers.py @@ -76,7 +76,7 @@ OEMBED_ENDPOINTS = { ], "http://api.instagram.com/oembed": [ "^http://instagr\\.am/p/.+$", - "^http://instagram\\.com/p/.+$" + "^http[s]?://instagram\\.com/p/.+$" ], "https://www.slideshare.net/api/oembed/2": [ "^http://www\\.slideshare\\.net/.+$"