Ver Fonte

Format code with black

Sage Abdullah há 2 anos atrás
pai
commit
40696f941c
39 ficheiros alterados com 3477 adições e 825 exclusões
  1. 4 4
      bakerydemo/api.py
  2. 26 14
      bakerydemo/base/blocks.py
  3. 14 12
      bakerydemo/base/management/commands/load_initial_data.py
  4. 720 83
      bakerydemo/base/migrations/0001_initial.py
  5. 327 13
      bakerydemo/base/migrations/0002_auto_20170329_0055.py
  6. 21 4
      bakerydemo/base/migrations/0003_auto_20170823_1127.py
  7. 32 7
      bakerydemo/base/migrations/0004_auto_20180522_1856.py
  8. 10 4
      bakerydemo/base/migrations/0005_formfield_clean_name.py
  9. 33 13
      bakerydemo/base/migrations/0006_char_field_remove_null.py
  10. 29 13
      bakerydemo/base/migrations/0007_alter_formfield_choices_and_more.py
  11. 331 13
      bakerydemo/base/migrations/0008_use_json_field_for_body_streamfield.py
  12. 146 128
      bakerydemo/base/models.py
  13. 3 3
      bakerydemo/base/templatetags/gallery_tags.py
  14. 27 22
      bakerydemo/base/templatetags/navigation_tags.py
  15. 19 16
      bakerydemo/base/wagtail_hooks.py
  16. 315 35
      bakerydemo/blog/migrations/0001_initial.py
  17. 3 3
      bakerydemo/blog/migrations/0002_remove_blogindexpage_body.py
  18. 83 4
      bakerydemo/blog/migrations/0003_auto_20170329_0055.py
  19. 9 5
      bakerydemo/blog/migrations/0004_alter_blogpagetag_tag.py
  20. 84 4
      bakerydemo/blog/migrations/0005_use_json_field_for_body_streamfield.py
  21. 43 52
      bakerydemo/blog/models.py
  22. 291 39
      bakerydemo/breads/migrations/0001_initial.py
  23. 3 3
      bakerydemo/breads/migrations/0002_remove_breadsindexpage_body.py
  24. 83 4
      bakerydemo/breads/migrations/0003_auto_20170329_0055.py
  25. 84 4
      bakerydemo/breads/migrations/0004_use_json_field_for_body_streamfield.py
  26. 34 38
      bakerydemo/breads/models.py
  27. 7 8
      bakerydemo/locations/choices.py
  28. 297 30
      bakerydemo/locations/migrations/0001_initial.py
  29. 3 3
      bakerydemo/locations/migrations/0002_remove_locationsindexpage_body.py
  30. 83 4
      bakerydemo/locations/migrations/0003_auto_20170329_0055.py
  31. 8 4
      bakerydemo/locations/migrations/0004_auto_20190912_1149.py
  32. 84 4
      bakerydemo/locations/migrations/0005_use_json_field_for_body_streamfield.py
  33. 51 71
      bakerydemo/locations/models.py
  34. 11 7
      bakerydemo/search/views.py
  35. 78 81
      bakerydemo/settings/base.py
  36. 3 3
      bakerydemo/settings/dev.py
  37. 65 53
      bakerydemo/settings/production.py
  38. 12 16
      bakerydemo/urls.py
  39. 1 1
      bakerydemo/wsgi.py

+ 4 - 4
bakerydemo/api.py

@@ -4,12 +4,12 @@ from wagtail.images.api.v2.views import ImagesAPIViewSet
 from wagtail.documents.api.v2.views import DocumentsAPIViewSet
 from wagtail.documents.api.v2.views import DocumentsAPIViewSet
 
 
 # Create the router. "wagtailapi" is the URL namespace
 # Create the router. "wagtailapi" is the URL namespace
-api_router = WagtailAPIRouter('wagtailapi')
+api_router = WagtailAPIRouter("wagtailapi")
 
 
 # Add the three endpoints using the "register_endpoint" method.
 # Add the three endpoints using the "register_endpoint" method.
 # The first parameter is the name of the endpoint (eg. pages, images). This
 # The first parameter is the name of the endpoint (eg. pages, images). This
 # is used in the URL of the endpoint
 # is used in the URL of the endpoint
 # The second parameter is the endpoint class that handles the requests
 # The second parameter is the endpoint class that handles the requests
-api_router.register_endpoint('pages', PagesAPIViewSet)
-api_router.register_endpoint('images', ImagesAPIViewSet)
-api_router.register_endpoint('documents', DocumentsAPIViewSet)
+api_router.register_endpoint("pages", PagesAPIViewSet)
+api_router.register_endpoint("images", ImagesAPIViewSet)
+api_router.register_endpoint("documents", DocumentsAPIViewSet)

+ 26 - 14
bakerydemo/base/blocks.py

@@ -1,7 +1,12 @@
 from wagtail.images.blocks import ImageChooserBlock
 from wagtail.images.blocks import ImageChooserBlock
 from wagtail.embeds.blocks import EmbedBlock
 from wagtail.embeds.blocks import EmbedBlock
 from wagtail.blocks import (
 from wagtail.blocks import (
-    CharBlock, ChoiceBlock, RichTextBlock, StreamBlock, StructBlock, TextBlock,
+    CharBlock,
+    ChoiceBlock,
+    RichTextBlock,
+    StreamBlock,
+    StructBlock,
+    TextBlock,
 )
 )
 
 
 
 
@@ -10,12 +15,13 @@ class ImageBlock(StructBlock):
     Custom `StructBlock` for utilizing images with associated caption and
     Custom `StructBlock` for utilizing images with associated caption and
     attribution data
     attribution data
     """
     """
+
     image = ImageChooserBlock(required=True)
     image = ImageChooserBlock(required=True)
     caption = CharBlock(required=False)
     caption = CharBlock(required=False)
     attribution = CharBlock(required=False)
     attribution = CharBlock(required=False)
 
 
     class Meta:
     class Meta:
-        icon = 'image'
+        icon = "image"
         template = "blocks/image_block.html"
         template = "blocks/image_block.html"
 
 
 
 
@@ -23,13 +29,18 @@ class HeadingBlock(StructBlock):
     """
     """
     Custom `StructBlock` that allows the user to select h2 - h4 sizes for headers
     Custom `StructBlock` that allows the user to select h2 - h4 sizes for headers
     """
     """
+
     heading_text = CharBlock(classname="title", required=True)
     heading_text = CharBlock(classname="title", required=True)
-    size = ChoiceBlock(choices=[
-        ('', 'Select a header size'),
-        ('h2', 'H2'),
-        ('h3', 'H3'),
-        ('h4', 'H4')
-    ], blank=True, required=False)
+    size = ChoiceBlock(
+        choices=[
+            ("", "Select a header size"),
+            ("h2", "H2"),
+            ("h3", "H3"),
+            ("h4", "H4"),
+        ],
+        blank=True,
+        required=False,
+    )
 
 
     class Meta:
     class Meta:
         icon = "title"
         icon = "title"
@@ -40,9 +51,9 @@ class BlockQuote(StructBlock):
     """
     """
     Custom `StructBlock` that allows the user to attribute a quote to the author
     Custom `StructBlock` that allows the user to attribute a quote to the author
     """
     """
+
     text = TextBlock()
     text = TextBlock()
-    attribute_name = CharBlock(
-        blank=True, required=False, label='e.g. Mary Berry')
+    attribute_name = CharBlock(blank=True, required=False, label="e.g. Mary Berry")
 
 
     class Meta:
     class Meta:
         icon = "fa-quote-left"
         icon = "fa-quote-left"
@@ -54,14 +65,15 @@ class BaseStreamBlock(StreamBlock):
     """
     """
     Define the custom blocks that `StreamField` will utilize
     Define the custom blocks that `StreamField` will utilize
     """
     """
+
     heading_block = HeadingBlock()
     heading_block = HeadingBlock()
     paragraph_block = RichTextBlock(
     paragraph_block = RichTextBlock(
-        icon="fa-paragraph",
-        template="blocks/paragraph_block.html"
+        icon="fa-paragraph", template="blocks/paragraph_block.html"
     )
     )
     image_block = ImageBlock()
     image_block = ImageBlock()
     block_quote = BlockQuote()
     block_quote = BlockQuote()
     embed_block = EmbedBlock(
     embed_block = EmbedBlock(
-        help_text='Insert an embed URL e.g https://www.youtube.com/embed/SGJFWirQ3ks',
+        help_text="Insert an embed URL e.g https://www.youtube.com/embed/SGJFWirQ3ks",
         icon="fa-s15",
         icon="fa-s15",
-        template="blocks/embed_block.html")
+        template="blocks/embed_block.html",
+    )

+ 14 - 12
bakerydemo/base/management/commands/load_initial_data.py

@@ -18,27 +18,29 @@ class Command(BaseCommand):
         """
         """
         directories, file_names = local_storage.listdir(path)
         directories, file_names = local_storage.listdir(path)
         for directory in directories:
         for directory in directories:
-            self._copy_files(local_storage, path + directory + '/')
+            self._copy_files(local_storage, path + directory + "/")
         for file_name in file_names:
         for file_name in file_names:
             with local_storage.open(path + file_name) as file_:
             with local_storage.open(path + file_name) as file_:
                 default_storage.save(path + file_name, file_)
                 default_storage.save(path + file_name, file_)
 
 
     def handle(self, **options):
     def handle(self, **options):
-        fixtures_dir = os.path.join(settings.PROJECT_DIR, 'base', 'fixtures')
-        fixture_file = os.path.join(fixtures_dir, 'bakerydemo.json')
+        fixtures_dir = os.path.join(settings.PROJECT_DIR, "base", "fixtures")
+        fixture_file = os.path.join(fixtures_dir, "bakerydemo.json")
 
 
         print("Copying media files to configured storage...")
         print("Copying media files to configured storage...")
-        local_storage = FileSystemStorage(os.path.join(fixtures_dir, 'media'))
-        self._copy_files(local_storage, '')  # file storage paths are relative
+        local_storage = FileSystemStorage(os.path.join(fixtures_dir, "media"))
+        self._copy_files(local_storage, "")  # file storage paths are relative
 
 
         # Wagtail creates default Site and Page instances during install, but we already have
         # Wagtail creates default Site and Page instances during install, but we already have
         # them in the data load. Remove the auto-generated ones.
         # them in the data load. Remove the auto-generated ones.
-        if Site.objects.filter(hostname='localhost').exists():
-            Site.objects.get(hostname='localhost').delete()
-        if Page.objects.filter(title='Welcome to your new Wagtail site!').exists():
-            Page.objects.get(title='Welcome to your new Wagtail site!').delete()
+        if Site.objects.filter(hostname="localhost").exists():
+            Site.objects.get(hostname="localhost").delete()
+        if Page.objects.filter(title="Welcome to your new Wagtail site!").exists():
+            Page.objects.get(title="Welcome to your new Wagtail site!").delete()
 
 
-        call_command('loaddata', fixture_file, verbosity=0)
-        call_command('update_index', verbosity=0)
+        call_command("loaddata", fixture_file, verbosity=0)
+        call_command("update_index", verbosity=0)
 
 
-        print("Awesome. Your data is loaded! The bakery's doors are almost ready to open...")
+        print(
+            "Awesome. Your data is loaded! The bakery's doors are almost ready to open..."
+        )

+ 720 - 83
bakerydemo/base/migrations/0001_initial.py

@@ -16,146 +16,783 @@ class Migration(migrations.Migration):
     initial = True
     initial = True
 
 
     dependencies = [
     dependencies = [
-        ('wagtailimages', '0018_remove_rendition_filter'),
-        ('wagtailcore', '0032_add_bulk_delete_page_permission'),
+        ("wagtailimages", "0018_remove_rendition_filter"),
+        ("wagtailcore", "0032_add_bulk_delete_page_permission"),
     ]
     ]
 
 
     operations = [
     operations = [
         migrations.CreateModel(
         migrations.CreateModel(
-            name='FooterText',
+            name="FooterText",
             fields=[
             fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('body', wagtail.fields.RichTextField()),
+                (
+                    "id",
+                    models.AutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                ("body", wagtail.fields.RichTextField()),
             ],
             ],
             options={
             options={
-                'verbose_name_plural': 'Footer Text',
+                "verbose_name_plural": "Footer Text",
             },
             },
         ),
         ),
         migrations.CreateModel(
         migrations.CreateModel(
-            name='FormField',
+            name="FormField",
             fields=[
             fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('sort_order', models.IntegerField(blank=True, editable=False, null=True)),
-                ('label', models.CharField(help_text='The label of the form field', max_length=255, verbose_name='label')),
-                ('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, verbose_name='field type')),
-                ('required', models.BooleanField(default=True, verbose_name='required')),
-                ('choices', models.TextField(blank=True, help_text='Comma separated list of choices. Only applicable in checkboxes, radio and dropdown.', verbose_name='choices')),
-                ('default_value', models.CharField(blank=True, help_text='Default value. Comma separated values supported for checkboxes.', max_length=255, verbose_name='default value')),
-                ('help_text', models.CharField(blank=True, max_length=255, verbose_name='help text')),
+                (
+                    "id",
+                    models.AutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                (
+                    "sort_order",
+                    models.IntegerField(blank=True, editable=False, null=True),
+                ),
+                (
+                    "label",
+                    models.CharField(
+                        help_text="The label of the form field",
+                        max_length=255,
+                        verbose_name="label",
+                    ),
+                ),
+                (
+                    "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,
+                        verbose_name="field type",
+                    ),
+                ),
+                (
+                    "required",
+                    models.BooleanField(default=True, verbose_name="required"),
+                ),
+                (
+                    "choices",
+                    models.TextField(
+                        blank=True,
+                        help_text="Comma separated list of choices. Only applicable in checkboxes, radio and dropdown.",
+                        verbose_name="choices",
+                    ),
+                ),
+                (
+                    "default_value",
+                    models.CharField(
+                        blank=True,
+                        help_text="Default value. Comma separated values supported for checkboxes.",
+                        max_length=255,
+                        verbose_name="default value",
+                    ),
+                ),
+                (
+                    "help_text",
+                    models.CharField(
+                        blank=True, max_length=255, verbose_name="help text"
+                    ),
+                ),
             ],
             ],
             options={
             options={
-                'ordering': ['sort_order'],
-                'abstract': False,
+                "ordering": ["sort_order"],
+                "abstract": False,
             },
             },
         ),
         ),
         migrations.CreateModel(
         migrations.CreateModel(
-            name='FormPage',
+            name="FormPage",
             fields=[
             fields=[
-                ('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.Page')),
-                ('to_address', models.CharField(blank=True, help_text='Optional - form submissions will be emailed to these addresses. Separate multiple addresses by comma.', max_length=255, verbose_name='to address')),
-                ('from_address', models.CharField(blank=True, max_length=255, verbose_name='from address')),
-                ('subject', models.CharField(blank=True, max_length=255, verbose_name='subject')),
-                ('body', wagtail.fields.StreamField((('heading_block', wagtail.blocks.StructBlock((('heading_text', wagtail.blocks.CharBlock(classname='title', required=True)), ('size', wagtail.blocks.ChoiceBlock(blank=True, choices=[('', 'Select a header size'), ('h2', 'H2'), ('h3', 'H3'), ('h4', 'H4')], required=False))))), ('paragraph_block', wagtail.blocks.RichTextBlock(icon='fa-paragraph', template='blocks/paragraph_block.html')), ('image_block', wagtail.blocks.StructBlock((('image', wagtail.images.blocks.ImageChooserBlock(required=True)), ('caption', wagtail.blocks.CharBlock(required=False)), ('attribution', wagtail.blocks.CharBlock(required=False))))), ('block_quote', wagtail.blocks.StructBlock((('text', wagtail.blocks.TextBlock()), ('attribute_name', wagtail.blocks.CharBlock(blank=True, label='e.g. Guy Picciotto', required=False))))), ('embed_block', wagtail.embeds.blocks.EmbedBlock(help_text='Insert an embed URL e.g https://www.youtube.com/embed/SGJFWirQ3ks', icon='fa-s15', template='blocks/embed_block.html'))))),
-                ('thank_you_text', wagtail.fields.RichTextField(blank=True)),
-                ('image', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailimages.Image')),
+                (
+                    "page_ptr",
+                    models.OneToOneField(
+                        auto_created=True,
+                        on_delete=django.db.models.deletion.CASCADE,
+                        parent_link=True,
+                        primary_key=True,
+                        serialize=False,
+                        to="wagtailcore.Page",
+                    ),
+                ),
+                (
+                    "to_address",
+                    models.CharField(
+                        blank=True,
+                        help_text="Optional - form submissions will be emailed to these addresses. Separate multiple addresses by comma.",
+                        max_length=255,
+                        verbose_name="to address",
+                    ),
+                ),
+                (
+                    "from_address",
+                    models.CharField(
+                        blank=True, max_length=255, verbose_name="from address"
+                    ),
+                ),
+                (
+                    "subject",
+                    models.CharField(
+                        blank=True, max_length=255, verbose_name="subject"
+                    ),
+                ),
+                (
+                    "body",
+                    wagtail.fields.StreamField(
+                        (
+                            (
+                                "heading_block",
+                                wagtail.blocks.StructBlock(
+                                    (
+                                        (
+                                            "heading_text",
+                                            wagtail.blocks.CharBlock(
+                                                classname="title", required=True
+                                            ),
+                                        ),
+                                        (
+                                            "size",
+                                            wagtail.blocks.ChoiceBlock(
+                                                blank=True,
+                                                choices=[
+                                                    ("", "Select a header size"),
+                                                    ("h2", "H2"),
+                                                    ("h3", "H3"),
+                                                    ("h4", "H4"),
+                                                ],
+                                                required=False,
+                                            ),
+                                        ),
+                                    )
+                                ),
+                            ),
+                            (
+                                "paragraph_block",
+                                wagtail.blocks.RichTextBlock(
+                                    icon="fa-paragraph",
+                                    template="blocks/paragraph_block.html",
+                                ),
+                            ),
+                            (
+                                "image_block",
+                                wagtail.blocks.StructBlock(
+                                    (
+                                        (
+                                            "image",
+                                            wagtail.images.blocks.ImageChooserBlock(
+                                                required=True
+                                            ),
+                                        ),
+                                        (
+                                            "caption",
+                                            wagtail.blocks.CharBlock(required=False),
+                                        ),
+                                        (
+                                            "attribution",
+                                            wagtail.blocks.CharBlock(required=False),
+                                        ),
+                                    )
+                                ),
+                            ),
+                            (
+                                "block_quote",
+                                wagtail.blocks.StructBlock(
+                                    (
+                                        ("text", wagtail.blocks.TextBlock()),
+                                        (
+                                            "attribute_name",
+                                            wagtail.blocks.CharBlock(
+                                                blank=True,
+                                                label="e.g. Guy Picciotto",
+                                                required=False,
+                                            ),
+                                        ),
+                                    )
+                                ),
+                            ),
+                            (
+                                "embed_block",
+                                wagtail.embeds.blocks.EmbedBlock(
+                                    help_text="Insert an embed URL e.g https://www.youtube.com/embed/SGJFWirQ3ks",
+                                    icon="fa-s15",
+                                    template="blocks/embed_block.html",
+                                ),
+                            ),
+                        )
+                    ),
+                ),
+                ("thank_you_text", wagtail.fields.RichTextField(blank=True)),
+                (
+                    "image",
+                    models.ForeignKey(
+                        blank=True,
+                        null=True,
+                        on_delete=django.db.models.deletion.SET_NULL,
+                        related_name="+",
+                        to="wagtailimages.Image",
+                    ),
+                ),
             ],
             ],
             options={
             options={
-                'abstract': False,
+                "abstract": False,
             },
             },
-            bases=('wagtailcore.page',),
+            bases=("wagtailcore.page",),
         ),
         ),
         migrations.CreateModel(
         migrations.CreateModel(
-            name='GalleryPage',
+            name="GalleryPage",
             fields=[
             fields=[
-                ('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.Page')),
-                ('introduction', models.TextField(blank=True, help_text='Text to describe the page')),
-                ('body', wagtail.fields.StreamField((('heading_block', wagtail.blocks.StructBlock((('heading_text', wagtail.blocks.CharBlock(classname='title', required=True)), ('size', wagtail.blocks.ChoiceBlock(blank=True, choices=[('', 'Select a header size'), ('h2', 'H2'), ('h3', 'H3'), ('h4', 'H4')], required=False))))), ('paragraph_block', wagtail.blocks.RichTextBlock(icon='fa-paragraph', template='blocks/paragraph_block.html')), ('image_block', wagtail.blocks.StructBlock((('image', wagtail.images.blocks.ImageChooserBlock(required=True)), ('caption', wagtail.blocks.CharBlock(required=False)), ('attribution', wagtail.blocks.CharBlock(required=False))))), ('block_quote', wagtail.blocks.StructBlock((('text', wagtail.blocks.TextBlock()), ('attribute_name', wagtail.blocks.CharBlock(blank=True, label='e.g. Guy Picciotto', required=False))))), ('embed_block', wagtail.embeds.blocks.EmbedBlock(help_text='Insert an embed URL e.g https://www.youtube.com/embed/SGJFWirQ3ks', icon='fa-s15', template='blocks/embed_block.html'))), blank=True, verbose_name='Page body')),
-                ('collection', models.ForeignKey(blank=True, help_text='Select the image collection for this gallery.', null=True, on_delete=django.db.models.deletion.SET_NULL, to='wagtailcore.Collection')),
-                ('image', models.ForeignKey(blank=True, help_text='Landscape mode only; horizontal width between 1000px and 3000px.', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailimages.Image')),
+                (
+                    "page_ptr",
+                    models.OneToOneField(
+                        auto_created=True,
+                        on_delete=django.db.models.deletion.CASCADE,
+                        parent_link=True,
+                        primary_key=True,
+                        serialize=False,
+                        to="wagtailcore.Page",
+                    ),
+                ),
+                (
+                    "introduction",
+                    models.TextField(blank=True, help_text="Text to describe the page"),
+                ),
+                (
+                    "body",
+                    wagtail.fields.StreamField(
+                        (
+                            (
+                                "heading_block",
+                                wagtail.blocks.StructBlock(
+                                    (
+                                        (
+                                            "heading_text",
+                                            wagtail.blocks.CharBlock(
+                                                classname="title", required=True
+                                            ),
+                                        ),
+                                        (
+                                            "size",
+                                            wagtail.blocks.ChoiceBlock(
+                                                blank=True,
+                                                choices=[
+                                                    ("", "Select a header size"),
+                                                    ("h2", "H2"),
+                                                    ("h3", "H3"),
+                                                    ("h4", "H4"),
+                                                ],
+                                                required=False,
+                                            ),
+                                        ),
+                                    )
+                                ),
+                            ),
+                            (
+                                "paragraph_block",
+                                wagtail.blocks.RichTextBlock(
+                                    icon="fa-paragraph",
+                                    template="blocks/paragraph_block.html",
+                                ),
+                            ),
+                            (
+                                "image_block",
+                                wagtail.blocks.StructBlock(
+                                    (
+                                        (
+                                            "image",
+                                            wagtail.images.blocks.ImageChooserBlock(
+                                                required=True
+                                            ),
+                                        ),
+                                        (
+                                            "caption",
+                                            wagtail.blocks.CharBlock(required=False),
+                                        ),
+                                        (
+                                            "attribution",
+                                            wagtail.blocks.CharBlock(required=False),
+                                        ),
+                                    )
+                                ),
+                            ),
+                            (
+                                "block_quote",
+                                wagtail.blocks.StructBlock(
+                                    (
+                                        ("text", wagtail.blocks.TextBlock()),
+                                        (
+                                            "attribute_name",
+                                            wagtail.blocks.CharBlock(
+                                                blank=True,
+                                                label="e.g. Guy Picciotto",
+                                                required=False,
+                                            ),
+                                        ),
+                                    )
+                                ),
+                            ),
+                            (
+                                "embed_block",
+                                wagtail.embeds.blocks.EmbedBlock(
+                                    help_text="Insert an embed URL e.g https://www.youtube.com/embed/SGJFWirQ3ks",
+                                    icon="fa-s15",
+                                    template="blocks/embed_block.html",
+                                ),
+                            ),
+                        ),
+                        blank=True,
+                        verbose_name="Page body",
+                    ),
+                ),
+                (
+                    "collection",
+                    models.ForeignKey(
+                        blank=True,
+                        help_text="Select the image collection for this gallery.",
+                        null=True,
+                        on_delete=django.db.models.deletion.SET_NULL,
+                        to="wagtailcore.Collection",
+                    ),
+                ),
+                (
+                    "image",
+                    models.ForeignKey(
+                        blank=True,
+                        help_text="Landscape mode only; horizontal width between 1000px and 3000px.",
+                        null=True,
+                        on_delete=django.db.models.deletion.SET_NULL,
+                        related_name="+",
+                        to="wagtailimages.Image",
+                    ),
+                ),
             ],
             ],
             options={
             options={
-                'abstract': False,
+                "abstract": False,
             },
             },
-            bases=('wagtailcore.page', models.Model),
+            bases=("wagtailcore.page", models.Model),
         ),
         ),
         migrations.CreateModel(
         migrations.CreateModel(
-            name='HomePage',
+            name="HomePage",
             fields=[
             fields=[
-                ('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.Page')),
-                ('hero_text', models.CharField(help_text='Write an introduction for the bakery', max_length=255)),
-                ('hero_cta', models.CharField(help_text='Text to display on Call to Action', max_length=255, verbose_name='Hero CTA')),
-                ('body', wagtail.fields.StreamField((('heading_block', wagtail.blocks.StructBlock((('heading_text', wagtail.blocks.CharBlock(classname='title', required=True)), ('size', wagtail.blocks.ChoiceBlock(blank=True, choices=[('', 'Select a header size'), ('h2', 'H2'), ('h3', 'H3'), ('h4', 'H4')], required=False))))), ('paragraph_block', wagtail.blocks.RichTextBlock(icon='fa-paragraph', template='blocks/paragraph_block.html')), ('image_block', wagtail.blocks.StructBlock((('image', wagtail.images.blocks.ImageChooserBlock(required=True)), ('caption', wagtail.blocks.CharBlock(required=False)), ('attribution', wagtail.blocks.CharBlock(required=False))))), ('block_quote', wagtail.blocks.StructBlock((('text', wagtail.blocks.TextBlock()), ('attribute_name', wagtail.blocks.CharBlock(blank=True, label='e.g. Guy Picciotto', required=False))))), ('embed_block', wagtail.embeds.blocks.EmbedBlock(help_text='Insert an embed URL e.g https://www.youtube.com/embed/SGJFWirQ3ks', icon='fa-s15', template='blocks/embed_block.html'))), blank=True, verbose_name='Home content block')),
-                ('promo_title', models.CharField(blank=True, help_text='Title to display above the promo copy', max_length=255, null=True)),
-                ('promo_text', wagtail.fields.RichTextField(blank=True, help_text='Write some promotional copy', null=True)),
-                ('featured_section_1_title', models.CharField(blank=True, help_text='Title to display above the promo copy', max_length=255, null=True)),
-                ('featured_section_2_title', models.CharField(blank=True, help_text='Title to display above the promo copy', max_length=255, null=True)),
-                ('featured_section_3_title', models.CharField(blank=True, help_text='Title to display above the promo copy', max_length=255, null=True)),
+                (
+                    "page_ptr",
+                    models.OneToOneField(
+                        auto_created=True,
+                        on_delete=django.db.models.deletion.CASCADE,
+                        parent_link=True,
+                        primary_key=True,
+                        serialize=False,
+                        to="wagtailcore.Page",
+                    ),
+                ),
+                (
+                    "hero_text",
+                    models.CharField(
+                        help_text="Write an introduction for the bakery", max_length=255
+                    ),
+                ),
+                (
+                    "hero_cta",
+                    models.CharField(
+                        help_text="Text to display on Call to Action",
+                        max_length=255,
+                        verbose_name="Hero CTA",
+                    ),
+                ),
+                (
+                    "body",
+                    wagtail.fields.StreamField(
+                        (
+                            (
+                                "heading_block",
+                                wagtail.blocks.StructBlock(
+                                    (
+                                        (
+                                            "heading_text",
+                                            wagtail.blocks.CharBlock(
+                                                classname="title", required=True
+                                            ),
+                                        ),
+                                        (
+                                            "size",
+                                            wagtail.blocks.ChoiceBlock(
+                                                blank=True,
+                                                choices=[
+                                                    ("", "Select a header size"),
+                                                    ("h2", "H2"),
+                                                    ("h3", "H3"),
+                                                    ("h4", "H4"),
+                                                ],
+                                                required=False,
+                                            ),
+                                        ),
+                                    )
+                                ),
+                            ),
+                            (
+                                "paragraph_block",
+                                wagtail.blocks.RichTextBlock(
+                                    icon="fa-paragraph",
+                                    template="blocks/paragraph_block.html",
+                                ),
+                            ),
+                            (
+                                "image_block",
+                                wagtail.blocks.StructBlock(
+                                    (
+                                        (
+                                            "image",
+                                            wagtail.images.blocks.ImageChooserBlock(
+                                                required=True
+                                            ),
+                                        ),
+                                        (
+                                            "caption",
+                                            wagtail.blocks.CharBlock(required=False),
+                                        ),
+                                        (
+                                            "attribution",
+                                            wagtail.blocks.CharBlock(required=False),
+                                        ),
+                                    )
+                                ),
+                            ),
+                            (
+                                "block_quote",
+                                wagtail.blocks.StructBlock(
+                                    (
+                                        ("text", wagtail.blocks.TextBlock()),
+                                        (
+                                            "attribute_name",
+                                            wagtail.blocks.CharBlock(
+                                                blank=True,
+                                                label="e.g. Guy Picciotto",
+                                                required=False,
+                                            ),
+                                        ),
+                                    )
+                                ),
+                            ),
+                            (
+                                "embed_block",
+                                wagtail.embeds.blocks.EmbedBlock(
+                                    help_text="Insert an embed URL e.g https://www.youtube.com/embed/SGJFWirQ3ks",
+                                    icon="fa-s15",
+                                    template="blocks/embed_block.html",
+                                ),
+                            ),
+                        ),
+                        blank=True,
+                        verbose_name="Home content block",
+                    ),
+                ),
+                (
+                    "promo_title",
+                    models.CharField(
+                        blank=True,
+                        help_text="Title to display above the promo copy",
+                        max_length=255,
+                        null=True,
+                    ),
+                ),
+                (
+                    "promo_text",
+                    wagtail.fields.RichTextField(
+                        blank=True, help_text="Write some promotional copy", null=True
+                    ),
+                ),
+                (
+                    "featured_section_1_title",
+                    models.CharField(
+                        blank=True,
+                        help_text="Title to display above the promo copy",
+                        max_length=255,
+                        null=True,
+                    ),
+                ),
+                (
+                    "featured_section_2_title",
+                    models.CharField(
+                        blank=True,
+                        help_text="Title to display above the promo copy",
+                        max_length=255,
+                        null=True,
+                    ),
+                ),
+                (
+                    "featured_section_3_title",
+                    models.CharField(
+                        blank=True,
+                        help_text="Title to display above the promo copy",
+                        max_length=255,
+                        null=True,
+                    ),
+                ),
             ],
             ],
             options={
             options={
-                'abstract': False,
+                "abstract": False,
             },
             },
-            bases=('wagtailcore.page',),
+            bases=("wagtailcore.page",),
         ),
         ),
         migrations.CreateModel(
         migrations.CreateModel(
-            name='People',
+            name="People",
             fields=[
             fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('first_name', models.CharField(max_length=254, verbose_name='First name')),
-                ('last_name', models.CharField(max_length=254, verbose_name='Last name')),
-                ('job_title', models.CharField(max_length=254, verbose_name='Job title')),
-                ('image', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailimages.Image')),
+                (
+                    "id",
+                    models.AutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                (
+                    "first_name",
+                    models.CharField(max_length=254, verbose_name="First name"),
+                ),
+                (
+                    "last_name",
+                    models.CharField(max_length=254, verbose_name="Last name"),
+                ),
+                (
+                    "job_title",
+                    models.CharField(max_length=254, verbose_name="Job title"),
+                ),
+                (
+                    "image",
+                    models.ForeignKey(
+                        blank=True,
+                        null=True,
+                        on_delete=django.db.models.deletion.SET_NULL,
+                        related_name="+",
+                        to="wagtailimages.Image",
+                    ),
+                ),
             ],
             ],
             options={
             options={
-                'verbose_name_plural': 'People',
-                'verbose_name': 'Person',
+                "verbose_name_plural": "People",
+                "verbose_name": "Person",
             },
             },
         ),
         ),
         migrations.CreateModel(
         migrations.CreateModel(
-            name='StandardPage',
+            name="StandardPage",
             fields=[
             fields=[
-                ('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.Page')),
-                ('introduction', models.TextField(blank=True, help_text='Text to describe the page')),
-                ('body', wagtail.fields.StreamField((('heading_block', wagtail.blocks.StructBlock((('heading_text', wagtail.blocks.CharBlock(classname='title', required=True)), ('size', wagtail.blocks.ChoiceBlock(blank=True, choices=[('', 'Select a header size'), ('h2', 'H2'), ('h3', 'H3'), ('h4', 'H4')], required=False))))), ('paragraph_block', wagtail.blocks.RichTextBlock(icon='fa-paragraph', template='blocks/paragraph_block.html')), ('image_block', wagtail.blocks.StructBlock((('image', wagtail.images.blocks.ImageChooserBlock(required=True)), ('caption', wagtail.blocks.CharBlock(required=False)), ('attribution', wagtail.blocks.CharBlock(required=False))))), ('block_quote', wagtail.blocks.StructBlock((('text', wagtail.blocks.TextBlock()), ('attribute_name', wagtail.blocks.CharBlock(blank=True, label='e.g. Guy Picciotto', required=False))))), ('embed_block', wagtail.embeds.blocks.EmbedBlock(help_text='Insert an embed URL e.g https://www.youtube.com/embed/SGJFWirQ3ks', icon='fa-s15', template='blocks/embed_block.html'))), blank=True, verbose_name='Page body')),
-                ('image', models.ForeignKey(blank=True, help_text='Landscape mode only; horizontal width between 1000px and 3000px.', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailimages.Image')),
+                (
+                    "page_ptr",
+                    models.OneToOneField(
+                        auto_created=True,
+                        on_delete=django.db.models.deletion.CASCADE,
+                        parent_link=True,
+                        primary_key=True,
+                        serialize=False,
+                        to="wagtailcore.Page",
+                    ),
+                ),
+                (
+                    "introduction",
+                    models.TextField(blank=True, help_text="Text to describe the page"),
+                ),
+                (
+                    "body",
+                    wagtail.fields.StreamField(
+                        (
+                            (
+                                "heading_block",
+                                wagtail.blocks.StructBlock(
+                                    (
+                                        (
+                                            "heading_text",
+                                            wagtail.blocks.CharBlock(
+                                                classname="title", required=True
+                                            ),
+                                        ),
+                                        (
+                                            "size",
+                                            wagtail.blocks.ChoiceBlock(
+                                                blank=True,
+                                                choices=[
+                                                    ("", "Select a header size"),
+                                                    ("h2", "H2"),
+                                                    ("h3", "H3"),
+                                                    ("h4", "H4"),
+                                                ],
+                                                required=False,
+                                            ),
+                                        ),
+                                    )
+                                ),
+                            ),
+                            (
+                                "paragraph_block",
+                                wagtail.blocks.RichTextBlock(
+                                    icon="fa-paragraph",
+                                    template="blocks/paragraph_block.html",
+                                ),
+                            ),
+                            (
+                                "image_block",
+                                wagtail.blocks.StructBlock(
+                                    (
+                                        (
+                                            "image",
+                                            wagtail.images.blocks.ImageChooserBlock(
+                                                required=True
+                                            ),
+                                        ),
+                                        (
+                                            "caption",
+                                            wagtail.blocks.CharBlock(required=False),
+                                        ),
+                                        (
+                                            "attribution",
+                                            wagtail.blocks.CharBlock(required=False),
+                                        ),
+                                    )
+                                ),
+                            ),
+                            (
+                                "block_quote",
+                                wagtail.blocks.StructBlock(
+                                    (
+                                        ("text", wagtail.blocks.TextBlock()),
+                                        (
+                                            "attribute_name",
+                                            wagtail.blocks.CharBlock(
+                                                blank=True,
+                                                label="e.g. Guy Picciotto",
+                                                required=False,
+                                            ),
+                                        ),
+                                    )
+                                ),
+                            ),
+                            (
+                                "embed_block",
+                                wagtail.embeds.blocks.EmbedBlock(
+                                    help_text="Insert an embed URL e.g https://www.youtube.com/embed/SGJFWirQ3ks",
+                                    icon="fa-s15",
+                                    template="blocks/embed_block.html",
+                                ),
+                            ),
+                        ),
+                        blank=True,
+                        verbose_name="Page body",
+                    ),
+                ),
+                (
+                    "image",
+                    models.ForeignKey(
+                        blank=True,
+                        help_text="Landscape mode only; horizontal width between 1000px and 3000px.",
+                        null=True,
+                        on_delete=django.db.models.deletion.SET_NULL,
+                        related_name="+",
+                        to="wagtailimages.Image",
+                    ),
+                ),
             ],
             ],
             options={
             options={
-                'abstract': False,
+                "abstract": False,
             },
             },
-            bases=('wagtailcore.page', models.Model),
+            bases=("wagtailcore.page", models.Model),
         ),
         ),
         migrations.AddField(
         migrations.AddField(
-            model_name='homepage',
-            name='featured_section_1',
-            field=models.ForeignKey(blank=True, help_text='First featured section for the homepage. Will display up to three child items.', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailcore.Page', verbose_name='Featured section 1'),
+            model_name="homepage",
+            name="featured_section_1",
+            field=models.ForeignKey(
+                blank=True,
+                help_text="First featured section for the homepage. Will display up to three child items.",
+                null=True,
+                on_delete=django.db.models.deletion.SET_NULL,
+                related_name="+",
+                to="wagtailcore.Page",
+                verbose_name="Featured section 1",
+            ),
         ),
         ),
         migrations.AddField(
         migrations.AddField(
-            model_name='homepage',
-            name='featured_section_2',
-            field=models.ForeignKey(blank=True, help_text='Second featured section for the homepage. Will display up to three child items.', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailcore.Page', verbose_name='Featured section 2'),
+            model_name="homepage",
+            name="featured_section_2",
+            field=models.ForeignKey(
+                blank=True,
+                help_text="Second featured section for the homepage. Will display up to three child items.",
+                null=True,
+                on_delete=django.db.models.deletion.SET_NULL,
+                related_name="+",
+                to="wagtailcore.Page",
+                verbose_name="Featured section 2",
+            ),
         ),
         ),
         migrations.AddField(
         migrations.AddField(
-            model_name='homepage',
-            name='featured_section_3',
-            field=models.ForeignKey(blank=True, help_text='Third featured section for the homepage. Will display up to six child items.', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailcore.Page', verbose_name='Featured section 3'),
+            model_name="homepage",
+            name="featured_section_3",
+            field=models.ForeignKey(
+                blank=True,
+                help_text="Third featured section for the homepage. Will display up to six child items.",
+                null=True,
+                on_delete=django.db.models.deletion.SET_NULL,
+                related_name="+",
+                to="wagtailcore.Page",
+                verbose_name="Featured section 3",
+            ),
         ),
         ),
         migrations.AddField(
         migrations.AddField(
-            model_name='homepage',
-            name='hero_cta_link',
-            field=models.ForeignKey(blank=True, help_text='Choose a page to link to for the Call to Action', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailcore.Page', verbose_name='Hero CTA link'),
+            model_name="homepage",
+            name="hero_cta_link",
+            field=models.ForeignKey(
+                blank=True,
+                help_text="Choose a page to link to for the Call to Action",
+                null=True,
+                on_delete=django.db.models.deletion.SET_NULL,
+                related_name="+",
+                to="wagtailcore.Page",
+                verbose_name="Hero CTA link",
+            ),
         ),
         ),
         migrations.AddField(
         migrations.AddField(
-            model_name='homepage',
-            name='image',
-            field=models.ForeignKey(blank=True, help_text='Homepage image', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailimages.Image'),
+            model_name="homepage",
+            name="image",
+            field=models.ForeignKey(
+                blank=True,
+                help_text="Homepage image",
+                null=True,
+                on_delete=django.db.models.deletion.SET_NULL,
+                related_name="+",
+                to="wagtailimages.Image",
+            ),
         ),
         ),
         migrations.AddField(
         migrations.AddField(
-            model_name='homepage',
-            name='promo_image',
-            field=models.ForeignKey(blank=True, help_text='Promo image', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailimages.Image'),
+            model_name="homepage",
+            name="promo_image",
+            field=models.ForeignKey(
+                blank=True,
+                help_text="Promo image",
+                null=True,
+                on_delete=django.db.models.deletion.SET_NULL,
+                related_name="+",
+                to="wagtailimages.Image",
+            ),
         ),
         ),
         migrations.AddField(
         migrations.AddField(
-            model_name='formfield',
-            name='page',
-            field=modelcluster.fields.ParentalKey(on_delete=django.db.models.deletion.CASCADE, related_name='form_fields', to='base.FormPage'),
+            model_name="formfield",
+            name="page",
+            field=modelcluster.fields.ParentalKey(
+                on_delete=django.db.models.deletion.CASCADE,
+                related_name="form_fields",
+                to="base.FormPage",
+            ),
         ),
         ),
     ]
     ]

+ 327 - 13
bakerydemo/base/migrations/0002_auto_20170329_0055.py

@@ -12,28 +12,342 @@ import wagtail.images.blocks
 class Migration(migrations.Migration):
 class Migration(migrations.Migration):
 
 
     dependencies = [
     dependencies = [
-        ('base', '0001_initial'),
+        ("base", "0001_initial"),
     ]
     ]
 
 
     operations = [
     operations = [
         migrations.AlterField(
         migrations.AlterField(
-            model_name='formpage',
-            name='body',
-            field=wagtail.fields.StreamField((('heading_block', wagtail.blocks.StructBlock((('heading_text', wagtail.blocks.CharBlock(classname='title', required=True)), ('size', wagtail.blocks.ChoiceBlock(blank=True, choices=[('', 'Select a header size'), ('h2', 'H2'), ('h3', 'H3'), ('h4', 'H4')], required=False))))), ('paragraph_block', wagtail.blocks.RichTextBlock(icon='fa-paragraph', template='blocks/paragraph_block.html')), ('image_block', wagtail.blocks.StructBlock((('image', wagtail.images.blocks.ImageChooserBlock(required=True)), ('caption', wagtail.blocks.CharBlock(required=False)), ('attribution', wagtail.blocks.CharBlock(required=False))))), ('block_quote', wagtail.blocks.StructBlock((('text', wagtail.blocks.TextBlock()), ('attribute_name', wagtail.blocks.CharBlock(blank=True, label='e.g. Mary Berry', required=False))))), ('embed_block', wagtail.embeds.blocks.EmbedBlock(help_text='Insert an embed URL e.g https://www.youtube.com/embed/SGJFWirQ3ks', icon='fa-s15', template='blocks/embed_block.html')))),
+            model_name="formpage",
+            name="body",
+            field=wagtail.fields.StreamField(
+                (
+                    (
+                        "heading_block",
+                        wagtail.blocks.StructBlock(
+                            (
+                                (
+                                    "heading_text",
+                                    wagtail.blocks.CharBlock(
+                                        classname="title", required=True
+                                    ),
+                                ),
+                                (
+                                    "size",
+                                    wagtail.blocks.ChoiceBlock(
+                                        blank=True,
+                                        choices=[
+                                            ("", "Select a header size"),
+                                            ("h2", "H2"),
+                                            ("h3", "H3"),
+                                            ("h4", "H4"),
+                                        ],
+                                        required=False,
+                                    ),
+                                ),
+                            )
+                        ),
+                    ),
+                    (
+                        "paragraph_block",
+                        wagtail.blocks.RichTextBlock(
+                            icon="fa-paragraph", template="blocks/paragraph_block.html"
+                        ),
+                    ),
+                    (
+                        "image_block",
+                        wagtail.blocks.StructBlock(
+                            (
+                                (
+                                    "image",
+                                    wagtail.images.blocks.ImageChooserBlock(
+                                        required=True
+                                    ),
+                                ),
+                                ("caption", wagtail.blocks.CharBlock(required=False)),
+                                (
+                                    "attribution",
+                                    wagtail.blocks.CharBlock(required=False),
+                                ),
+                            )
+                        ),
+                    ),
+                    (
+                        "block_quote",
+                        wagtail.blocks.StructBlock(
+                            (
+                                ("text", wagtail.blocks.TextBlock()),
+                                (
+                                    "attribute_name",
+                                    wagtail.blocks.CharBlock(
+                                        blank=True,
+                                        label="e.g. Mary Berry",
+                                        required=False,
+                                    ),
+                                ),
+                            )
+                        ),
+                    ),
+                    (
+                        "embed_block",
+                        wagtail.embeds.blocks.EmbedBlock(
+                            help_text="Insert an embed URL e.g https://www.youtube.com/embed/SGJFWirQ3ks",
+                            icon="fa-s15",
+                            template="blocks/embed_block.html",
+                        ),
+                    ),
+                )
+            ),
         ),
         ),
         migrations.AlterField(
         migrations.AlterField(
-            model_name='gallerypage',
-            name='body',
-            field=wagtail.fields.StreamField((('heading_block', wagtail.blocks.StructBlock((('heading_text', wagtail.blocks.CharBlock(classname='title', required=True)), ('size', wagtail.blocks.ChoiceBlock(blank=True, choices=[('', 'Select a header size'), ('h2', 'H2'), ('h3', 'H3'), ('h4', 'H4')], required=False))))), ('paragraph_block', wagtail.blocks.RichTextBlock(icon='fa-paragraph', template='blocks/paragraph_block.html')), ('image_block', wagtail.blocks.StructBlock((('image', wagtail.images.blocks.ImageChooserBlock(required=True)), ('caption', wagtail.blocks.CharBlock(required=False)), ('attribution', wagtail.blocks.CharBlock(required=False))))), ('block_quote', wagtail.blocks.StructBlock((('text', wagtail.blocks.TextBlock()), ('attribute_name', wagtail.blocks.CharBlock(blank=True, label='e.g. Mary Berry', required=False))))), ('embed_block', wagtail.embeds.blocks.EmbedBlock(help_text='Insert an embed URL e.g https://www.youtube.com/embed/SGJFWirQ3ks', icon='fa-s15', template='blocks/embed_block.html'))), blank=True, verbose_name='Page body'),
+            model_name="gallerypage",
+            name="body",
+            field=wagtail.fields.StreamField(
+                (
+                    (
+                        "heading_block",
+                        wagtail.blocks.StructBlock(
+                            (
+                                (
+                                    "heading_text",
+                                    wagtail.blocks.CharBlock(
+                                        classname="title", required=True
+                                    ),
+                                ),
+                                (
+                                    "size",
+                                    wagtail.blocks.ChoiceBlock(
+                                        blank=True,
+                                        choices=[
+                                            ("", "Select a header size"),
+                                            ("h2", "H2"),
+                                            ("h3", "H3"),
+                                            ("h4", "H4"),
+                                        ],
+                                        required=False,
+                                    ),
+                                ),
+                            )
+                        ),
+                    ),
+                    (
+                        "paragraph_block",
+                        wagtail.blocks.RichTextBlock(
+                            icon="fa-paragraph", template="blocks/paragraph_block.html"
+                        ),
+                    ),
+                    (
+                        "image_block",
+                        wagtail.blocks.StructBlock(
+                            (
+                                (
+                                    "image",
+                                    wagtail.images.blocks.ImageChooserBlock(
+                                        required=True
+                                    ),
+                                ),
+                                ("caption", wagtail.blocks.CharBlock(required=False)),
+                                (
+                                    "attribution",
+                                    wagtail.blocks.CharBlock(required=False),
+                                ),
+                            )
+                        ),
+                    ),
+                    (
+                        "block_quote",
+                        wagtail.blocks.StructBlock(
+                            (
+                                ("text", wagtail.blocks.TextBlock()),
+                                (
+                                    "attribute_name",
+                                    wagtail.blocks.CharBlock(
+                                        blank=True,
+                                        label="e.g. Mary Berry",
+                                        required=False,
+                                    ),
+                                ),
+                            )
+                        ),
+                    ),
+                    (
+                        "embed_block",
+                        wagtail.embeds.blocks.EmbedBlock(
+                            help_text="Insert an embed URL e.g https://www.youtube.com/embed/SGJFWirQ3ks",
+                            icon="fa-s15",
+                            template="blocks/embed_block.html",
+                        ),
+                    ),
+                ),
+                blank=True,
+                verbose_name="Page body",
+            ),
         ),
         ),
         migrations.AlterField(
         migrations.AlterField(
-            model_name='homepage',
-            name='body',
-            field=wagtail.fields.StreamField((('heading_block', wagtail.blocks.StructBlock((('heading_text', wagtail.blocks.CharBlock(classname='title', required=True)), ('size', wagtail.blocks.ChoiceBlock(blank=True, choices=[('', 'Select a header size'), ('h2', 'H2'), ('h3', 'H3'), ('h4', 'H4')], required=False))))), ('paragraph_block', wagtail.blocks.RichTextBlock(icon='fa-paragraph', template='blocks/paragraph_block.html')), ('image_block', wagtail.blocks.StructBlock((('image', wagtail.images.blocks.ImageChooserBlock(required=True)), ('caption', wagtail.blocks.CharBlock(required=False)), ('attribution', wagtail.blocks.CharBlock(required=False))))), ('block_quote', wagtail.blocks.StructBlock((('text', wagtail.blocks.TextBlock()), ('attribute_name', wagtail.blocks.CharBlock(blank=True, label='e.g. Mary Berry', required=False))))), ('embed_block', wagtail.embeds.blocks.EmbedBlock(help_text='Insert an embed URL e.g https://www.youtube.com/embed/SGJFWirQ3ks', icon='fa-s15', template='blocks/embed_block.html'))), blank=True, verbose_name='Home content block'),
+            model_name="homepage",
+            name="body",
+            field=wagtail.fields.StreamField(
+                (
+                    (
+                        "heading_block",
+                        wagtail.blocks.StructBlock(
+                            (
+                                (
+                                    "heading_text",
+                                    wagtail.blocks.CharBlock(
+                                        classname="title", required=True
+                                    ),
+                                ),
+                                (
+                                    "size",
+                                    wagtail.blocks.ChoiceBlock(
+                                        blank=True,
+                                        choices=[
+                                            ("", "Select a header size"),
+                                            ("h2", "H2"),
+                                            ("h3", "H3"),
+                                            ("h4", "H4"),
+                                        ],
+                                        required=False,
+                                    ),
+                                ),
+                            )
+                        ),
+                    ),
+                    (
+                        "paragraph_block",
+                        wagtail.blocks.RichTextBlock(
+                            icon="fa-paragraph", template="blocks/paragraph_block.html"
+                        ),
+                    ),
+                    (
+                        "image_block",
+                        wagtail.blocks.StructBlock(
+                            (
+                                (
+                                    "image",
+                                    wagtail.images.blocks.ImageChooserBlock(
+                                        required=True
+                                    ),
+                                ),
+                                ("caption", wagtail.blocks.CharBlock(required=False)),
+                                (
+                                    "attribution",
+                                    wagtail.blocks.CharBlock(required=False),
+                                ),
+                            )
+                        ),
+                    ),
+                    (
+                        "block_quote",
+                        wagtail.blocks.StructBlock(
+                            (
+                                ("text", wagtail.blocks.TextBlock()),
+                                (
+                                    "attribute_name",
+                                    wagtail.blocks.CharBlock(
+                                        blank=True,
+                                        label="e.g. Mary Berry",
+                                        required=False,
+                                    ),
+                                ),
+                            )
+                        ),
+                    ),
+                    (
+                        "embed_block",
+                        wagtail.embeds.blocks.EmbedBlock(
+                            help_text="Insert an embed URL e.g https://www.youtube.com/embed/SGJFWirQ3ks",
+                            icon="fa-s15",
+                            template="blocks/embed_block.html",
+                        ),
+                    ),
+                ),
+                blank=True,
+                verbose_name="Home content block",
+            ),
         ),
         ),
         migrations.AlterField(
         migrations.AlterField(
-            model_name='standardpage',
-            name='body',
-            field=wagtail.fields.StreamField((('heading_block', wagtail.blocks.StructBlock((('heading_text', wagtail.blocks.CharBlock(classname='title', required=True)), ('size', wagtail.blocks.ChoiceBlock(blank=True, choices=[('', 'Select a header size'), ('h2', 'H2'), ('h3', 'H3'), ('h4', 'H4')], required=False))))), ('paragraph_block', wagtail.blocks.RichTextBlock(icon='fa-paragraph', template='blocks/paragraph_block.html')), ('image_block', wagtail.blocks.StructBlock((('image', wagtail.images.blocks.ImageChooserBlock(required=True)), ('caption', wagtail.blocks.CharBlock(required=False)), ('attribution', wagtail.blocks.CharBlock(required=False))))), ('block_quote', wagtail.blocks.StructBlock((('text', wagtail.blocks.TextBlock()), ('attribute_name', wagtail.blocks.CharBlock(blank=True, label='e.g. Mary Berry', required=False))))), ('embed_block', wagtail.embeds.blocks.EmbedBlock(help_text='Insert an embed URL e.g https://www.youtube.com/embed/SGJFWirQ3ks', icon='fa-s15', template='blocks/embed_block.html'))), blank=True, verbose_name='Page body'),
+            model_name="standardpage",
+            name="body",
+            field=wagtail.fields.StreamField(
+                (
+                    (
+                        "heading_block",
+                        wagtail.blocks.StructBlock(
+                            (
+                                (
+                                    "heading_text",
+                                    wagtail.blocks.CharBlock(
+                                        classname="title", required=True
+                                    ),
+                                ),
+                                (
+                                    "size",
+                                    wagtail.blocks.ChoiceBlock(
+                                        blank=True,
+                                        choices=[
+                                            ("", "Select a header size"),
+                                            ("h2", "H2"),
+                                            ("h3", "H3"),
+                                            ("h4", "H4"),
+                                        ],
+                                        required=False,
+                                    ),
+                                ),
+                            )
+                        ),
+                    ),
+                    (
+                        "paragraph_block",
+                        wagtail.blocks.RichTextBlock(
+                            icon="fa-paragraph", template="blocks/paragraph_block.html"
+                        ),
+                    ),
+                    (
+                        "image_block",
+                        wagtail.blocks.StructBlock(
+                            (
+                                (
+                                    "image",
+                                    wagtail.images.blocks.ImageChooserBlock(
+                                        required=True
+                                    ),
+                                ),
+                                ("caption", wagtail.blocks.CharBlock(required=False)),
+                                (
+                                    "attribution",
+                                    wagtail.blocks.CharBlock(required=False),
+                                ),
+                            )
+                        ),
+                    ),
+                    (
+                        "block_quote",
+                        wagtail.blocks.StructBlock(
+                            (
+                                ("text", wagtail.blocks.TextBlock()),
+                                (
+                                    "attribute_name",
+                                    wagtail.blocks.CharBlock(
+                                        blank=True,
+                                        label="e.g. Mary Berry",
+                                        required=False,
+                                    ),
+                                ),
+                            )
+                        ),
+                    ),
+                    (
+                        "embed_block",
+                        wagtail.embeds.blocks.EmbedBlock(
+                            help_text="Insert an embed URL e.g https://www.youtube.com/embed/SGJFWirQ3ks",
+                            icon="fa-s15",
+                            template="blocks/embed_block.html",
+                        ),
+                    ),
+                ),
+                blank=True,
+                verbose_name="Page body",
+            ),
         ),
         ),
     ]
     ]

+ 21 - 4
bakerydemo/base/migrations/0003_auto_20170823_1127.py

@@ -8,13 +8,30 @@ from django.db import migrations, models
 class Migration(migrations.Migration):
 class Migration(migrations.Migration):
 
 
     dependencies = [
     dependencies = [
-        ('base', '0002_auto_20170329_0055'),
+        ("base", "0002_auto_20170329_0055"),
     ]
     ]
 
 
     operations = [
     operations = [
         migrations.AlterField(
         migrations.AlterField(
-            model_name='formfield',
-            name='field_type',
-            field=models.CharField(choices=[('singleline', 'Single line text'), ('multiline', 'Multi-line text'), ('email', 'Email'), ('number', 'Number'), ('url', 'URL'), ('checkbox', 'Checkbox'), ('checkboxes', 'Checkboxes'), ('dropdown', 'Drop down'), ('multiselect', 'Multiple select'), ('radio', 'Radio buttons'), ('date', 'Date'), ('datetime', 'Date/time')], max_length=16, verbose_name='field type'),
+            model_name="formfield",
+            name="field_type",
+            field=models.CharField(
+                choices=[
+                    ("singleline", "Single line text"),
+                    ("multiline", "Multi-line text"),
+                    ("email", "Email"),
+                    ("number", "Number"),
+                    ("url", "URL"),
+                    ("checkbox", "Checkbox"),
+                    ("checkboxes", "Checkboxes"),
+                    ("dropdown", "Drop down"),
+                    ("multiselect", "Multiple select"),
+                    ("radio", "Radio buttons"),
+                    ("date", "Date"),
+                    ("datetime", "Date/time"),
+                ],
+                max_length=16,
+                verbose_name="field type",
+            ),
         ),
         ),
     ]
     ]

+ 32 - 7
bakerydemo/base/migrations/0004_auto_20180522_1856.py

@@ -7,18 +7,43 @@ import django.db.models.deletion
 class Migration(migrations.Migration):
 class Migration(migrations.Migration):
 
 
     dependencies = [
     dependencies = [
-        ('base', '0003_auto_20170823_1127'),
+        ("base", "0003_auto_20170823_1127"),
     ]
     ]
 
 
     operations = [
     operations = [
         migrations.AlterField(
         migrations.AlterField(
-            model_name='formfield',
-            name='field_type',
-            field=models.CharField(choices=[('singleline', 'Single line text'), ('multiline', 'Multi-line text'), ('email', 'Email'), ('number', 'Number'), ('url', 'URL'), ('checkbox', 'Checkbox'), ('checkboxes', 'Checkboxes'), ('dropdown', 'Drop down'), ('multiselect', 'Multiple select'), ('radio', 'Radio buttons'), ('date', 'Date'), ('datetime', 'Date/time'), ('hidden', 'Hidden field')], max_length=16, verbose_name='field type'),
+            model_name="formfield",
+            name="field_type",
+            field=models.CharField(
+                choices=[
+                    ("singleline", "Single line text"),
+                    ("multiline", "Multi-line text"),
+                    ("email", "Email"),
+                    ("number", "Number"),
+                    ("url", "URL"),
+                    ("checkbox", "Checkbox"),
+                    ("checkboxes", "Checkboxes"),
+                    ("dropdown", "Drop down"),
+                    ("multiselect", "Multiple select"),
+                    ("radio", "Radio buttons"),
+                    ("date", "Date"),
+                    ("datetime", "Date/time"),
+                    ("hidden", "Hidden field"),
+                ],
+                max_length=16,
+                verbose_name="field type",
+            ),
         ),
         ),
         migrations.AlterField(
         migrations.AlterField(
-            model_name='gallerypage',
-            name='collection',
-            field=models.ForeignKey(blank=True, help_text='Select the image collection for this gallery.', limit_choices_to=models.Q(_negated=True, name__in=['Root']), null=True, on_delete=django.db.models.deletion.SET_NULL, to='wagtailcore.Collection'),
+            model_name="gallerypage",
+            name="collection",
+            field=models.ForeignKey(
+                blank=True,
+                help_text="Select the image collection for this gallery.",
+                limit_choices_to=models.Q(_negated=True, name__in=["Root"]),
+                null=True,
+                on_delete=django.db.models.deletion.SET_NULL,
+                to="wagtailcore.Collection",
+            ),
         ),
         ),
     ]
     ]

+ 10 - 4
bakerydemo/base/migrations/0005_formfield_clean_name.py

@@ -6,13 +6,19 @@ from django.db import migrations, models
 class Migration(migrations.Migration):
 class Migration(migrations.Migration):
 
 
     dependencies = [
     dependencies = [
-        ('base', '0004_auto_20180522_1856'),
+        ("base", "0004_auto_20180522_1856"),
     ]
     ]
 
 
     operations = [
     operations = [
         migrations.AddField(
         migrations.AddField(
-            model_name='formfield',
-            name='clean_name',
-            field=models.CharField(blank=True, default='', help_text='Safe name of the form field, the label converted to ascii_snake_case', max_length=255, verbose_name='name'),
+            model_name="formfield",
+            name="clean_name",
+            field=models.CharField(
+                blank=True,
+                default="",
+                help_text="Safe name of the form field, the label converted to ascii_snake_case",
+                max_length=255,
+                verbose_name="name",
+            ),
         ),
         ),
     ]
     ]

+ 33 - 13
bakerydemo/base/migrations/0006_char_field_remove_null.py

@@ -6,32 +6,52 @@ from django.db import migrations, models
 class Migration(migrations.Migration):
 class Migration(migrations.Migration):
 
 
     dependencies = [
     dependencies = [
-        ('base', '0005_formfield_clean_name'),
+        ("base", "0005_formfield_clean_name"),
     ]
     ]
 
 
     operations = [
     operations = [
         migrations.AlterField(
         migrations.AlterField(
-            model_name='homepage',
-            name='featured_section_1_title',
-            field=models.CharField(blank=True, default='', help_text='Title to display above the promo copy', max_length=255),
+            model_name="homepage",
+            name="featured_section_1_title",
+            field=models.CharField(
+                blank=True,
+                default="",
+                help_text="Title to display above the promo copy",
+                max_length=255,
+            ),
             preserve_default=False,
             preserve_default=False,
         ),
         ),
         migrations.AlterField(
         migrations.AlterField(
-            model_name='homepage',
-            name='featured_section_2_title',
-            field=models.CharField(blank=True, default='', help_text='Title to display above the promo copy', max_length=255),
+            model_name="homepage",
+            name="featured_section_2_title",
+            field=models.CharField(
+                blank=True,
+                default="",
+                help_text="Title to display above the promo copy",
+                max_length=255,
+            ),
             preserve_default=False,
             preserve_default=False,
         ),
         ),
         migrations.AlterField(
         migrations.AlterField(
-            model_name='homepage',
-            name='featured_section_3_title',
-            field=models.CharField(blank=True, default='', help_text='Title to display above the promo copy', max_length=255),
+            model_name="homepage",
+            name="featured_section_3_title",
+            field=models.CharField(
+                blank=True,
+                default="",
+                help_text="Title to display above the promo copy",
+                max_length=255,
+            ),
             preserve_default=False,
             preserve_default=False,
         ),
         ),
         migrations.AlterField(
         migrations.AlterField(
-            model_name='homepage',
-            name='promo_title',
-            field=models.CharField(blank=True, default='', help_text='Title to display above the promo copy', max_length=255),
+            model_name="homepage",
+            name="promo_title",
+            field=models.CharField(
+                blank=True,
+                default="",
+                help_text="Title to display above the promo copy",
+                max_length=255,
+            ),
             preserve_default=False,
             preserve_default=False,
         ),
         ),
     ]
     ]

+ 29 - 13
bakerydemo/base/migrations/0007_alter_formfield_choices_and_more.py

@@ -7,28 +7,44 @@ import wagtail.contrib.forms.models
 class Migration(migrations.Migration):
 class Migration(migrations.Migration):
 
 
     dependencies = [
     dependencies = [
-        ('base', '0006_char_field_remove_null'),
+        ("base", "0006_char_field_remove_null"),
     ]
     ]
 
 
     operations = [
     operations = [
         migrations.AlterField(
         migrations.AlterField(
-            model_name='formfield',
-            name='choices',
-            field=models.TextField(blank=True, help_text='Comma or new line separated list of choices. Only applicable in checkboxes, radio and dropdown.', verbose_name='choices'),
+            model_name="formfield",
+            name="choices",
+            field=models.TextField(
+                blank=True,
+                help_text="Comma or new line separated list of choices. Only applicable in checkboxes, radio and dropdown.",
+                verbose_name="choices",
+            ),
         ),
         ),
         migrations.AlterField(
         migrations.AlterField(
-            model_name='formfield',
-            name='default_value',
-            field=models.TextField(blank=True, help_text='Default value. Comma or new line separated values supported for checkboxes.', verbose_name='default value'),
+            model_name="formfield",
+            name="default_value",
+            field=models.TextField(
+                blank=True,
+                help_text="Default value. Comma or new line separated values supported for checkboxes.",
+                verbose_name="default value",
+            ),
         ),
         ),
         migrations.AlterField(
         migrations.AlterField(
-            model_name='formpage',
-            name='from_address',
-            field=models.EmailField(blank=True, max_length=255, verbose_name='from address'),
+            model_name="formpage",
+            name="from_address",
+            field=models.EmailField(
+                blank=True, max_length=255, verbose_name="from address"
+            ),
         ),
         ),
         migrations.AlterField(
         migrations.AlterField(
-            model_name='formpage',
-            name='to_address',
-            field=models.CharField(blank=True, help_text='Optional - form submissions will be emailed to these addresses. Separate multiple addresses by comma.', max_length=255, validators=[wagtail.contrib.forms.models.validate_to_address], verbose_name='to address'),
+            model_name="formpage",
+            name="to_address",
+            field=models.CharField(
+                blank=True,
+                help_text="Optional - form submissions will be emailed to these addresses. Separate multiple addresses by comma.",
+                max_length=255,
+                validators=[wagtail.contrib.forms.models.validate_to_address],
+                verbose_name="to address",
+            ),
         ),
         ),
     ]
     ]

+ 331 - 13
bakerydemo/base/migrations/0008_use_json_field_for_body_streamfield.py

@@ -10,28 +10,346 @@ import wagtail.images.blocks
 class Migration(migrations.Migration):
 class Migration(migrations.Migration):
 
 
     dependencies = [
     dependencies = [
-        ('base', '0007_alter_formfield_choices_and_more'),
+        ("base", "0007_alter_formfield_choices_and_more"),
     ]
     ]
 
 
     operations = [
     operations = [
         migrations.AlterField(
         migrations.AlterField(
-            model_name='formpage',
-            name='body',
-            field=wagtail.fields.StreamField([('heading_block', wagtail.blocks.StructBlock([('heading_text', wagtail.blocks.CharBlock(form_classname='title', required=True)), ('size', wagtail.blocks.ChoiceBlock(blank=True, choices=[('', 'Select a header size'), ('h2', 'H2'), ('h3', 'H3'), ('h4', 'H4')], required=False))])), ('paragraph_block', wagtail.blocks.RichTextBlock(icon='fa-paragraph', template='blocks/paragraph_block.html')), ('image_block', wagtail.blocks.StructBlock([('image', wagtail.images.blocks.ImageChooserBlock(required=True)), ('caption', wagtail.blocks.CharBlock(required=False)), ('attribution', wagtail.blocks.CharBlock(required=False))])), ('block_quote', wagtail.blocks.StructBlock([('text', wagtail.blocks.TextBlock()), ('attribute_name', wagtail.blocks.CharBlock(blank=True, label='e.g. Mary Berry', required=False))])), ('embed_block', wagtail.embeds.blocks.EmbedBlock(help_text='Insert an embed URL e.g https://www.youtube.com/embed/SGJFWirQ3ks', icon='fa-s15', template='blocks/embed_block.html'))], use_json_field=True),
+            model_name="formpage",
+            name="body",
+            field=wagtail.fields.StreamField(
+                [
+                    (
+                        "heading_block",
+                        wagtail.blocks.StructBlock(
+                            [
+                                (
+                                    "heading_text",
+                                    wagtail.blocks.CharBlock(
+                                        form_classname="title", required=True
+                                    ),
+                                ),
+                                (
+                                    "size",
+                                    wagtail.blocks.ChoiceBlock(
+                                        blank=True,
+                                        choices=[
+                                            ("", "Select a header size"),
+                                            ("h2", "H2"),
+                                            ("h3", "H3"),
+                                            ("h4", "H4"),
+                                        ],
+                                        required=False,
+                                    ),
+                                ),
+                            ]
+                        ),
+                    ),
+                    (
+                        "paragraph_block",
+                        wagtail.blocks.RichTextBlock(
+                            icon="fa-paragraph", template="blocks/paragraph_block.html"
+                        ),
+                    ),
+                    (
+                        "image_block",
+                        wagtail.blocks.StructBlock(
+                            [
+                                (
+                                    "image",
+                                    wagtail.images.blocks.ImageChooserBlock(
+                                        required=True
+                                    ),
+                                ),
+                                ("caption", wagtail.blocks.CharBlock(required=False)),
+                                (
+                                    "attribution",
+                                    wagtail.blocks.CharBlock(required=False),
+                                ),
+                            ]
+                        ),
+                    ),
+                    (
+                        "block_quote",
+                        wagtail.blocks.StructBlock(
+                            [
+                                ("text", wagtail.blocks.TextBlock()),
+                                (
+                                    "attribute_name",
+                                    wagtail.blocks.CharBlock(
+                                        blank=True,
+                                        label="e.g. Mary Berry",
+                                        required=False,
+                                    ),
+                                ),
+                            ]
+                        ),
+                    ),
+                    (
+                        "embed_block",
+                        wagtail.embeds.blocks.EmbedBlock(
+                            help_text="Insert an embed URL e.g https://www.youtube.com/embed/SGJFWirQ3ks",
+                            icon="fa-s15",
+                            template="blocks/embed_block.html",
+                        ),
+                    ),
+                ],
+                use_json_field=True,
+            ),
         ),
         ),
         migrations.AlterField(
         migrations.AlterField(
-            model_name='gallerypage',
-            name='body',
-            field=wagtail.fields.StreamField([('heading_block', wagtail.blocks.StructBlock([('heading_text', wagtail.blocks.CharBlock(form_classname='title', required=True)), ('size', wagtail.blocks.ChoiceBlock(blank=True, choices=[('', 'Select a header size'), ('h2', 'H2'), ('h3', 'H3'), ('h4', 'H4')], required=False))])), ('paragraph_block', wagtail.blocks.RichTextBlock(icon='fa-paragraph', template='blocks/paragraph_block.html')), ('image_block', wagtail.blocks.StructBlock([('image', wagtail.images.blocks.ImageChooserBlock(required=True)), ('caption', wagtail.blocks.CharBlock(required=False)), ('attribution', wagtail.blocks.CharBlock(required=False))])), ('block_quote', wagtail.blocks.StructBlock([('text', wagtail.blocks.TextBlock()), ('attribute_name', wagtail.blocks.CharBlock(blank=True, label='e.g. Mary Berry', required=False))])), ('embed_block', wagtail.embeds.blocks.EmbedBlock(help_text='Insert an embed URL e.g https://www.youtube.com/embed/SGJFWirQ3ks', icon='fa-s15', template='blocks/embed_block.html'))], blank=True, use_json_field=True, verbose_name='Page body'),
+            model_name="gallerypage",
+            name="body",
+            field=wagtail.fields.StreamField(
+                [
+                    (
+                        "heading_block",
+                        wagtail.blocks.StructBlock(
+                            [
+                                (
+                                    "heading_text",
+                                    wagtail.blocks.CharBlock(
+                                        form_classname="title", required=True
+                                    ),
+                                ),
+                                (
+                                    "size",
+                                    wagtail.blocks.ChoiceBlock(
+                                        blank=True,
+                                        choices=[
+                                            ("", "Select a header size"),
+                                            ("h2", "H2"),
+                                            ("h3", "H3"),
+                                            ("h4", "H4"),
+                                        ],
+                                        required=False,
+                                    ),
+                                ),
+                            ]
+                        ),
+                    ),
+                    (
+                        "paragraph_block",
+                        wagtail.blocks.RichTextBlock(
+                            icon="fa-paragraph", template="blocks/paragraph_block.html"
+                        ),
+                    ),
+                    (
+                        "image_block",
+                        wagtail.blocks.StructBlock(
+                            [
+                                (
+                                    "image",
+                                    wagtail.images.blocks.ImageChooserBlock(
+                                        required=True
+                                    ),
+                                ),
+                                ("caption", wagtail.blocks.CharBlock(required=False)),
+                                (
+                                    "attribution",
+                                    wagtail.blocks.CharBlock(required=False),
+                                ),
+                            ]
+                        ),
+                    ),
+                    (
+                        "block_quote",
+                        wagtail.blocks.StructBlock(
+                            [
+                                ("text", wagtail.blocks.TextBlock()),
+                                (
+                                    "attribute_name",
+                                    wagtail.blocks.CharBlock(
+                                        blank=True,
+                                        label="e.g. Mary Berry",
+                                        required=False,
+                                    ),
+                                ),
+                            ]
+                        ),
+                    ),
+                    (
+                        "embed_block",
+                        wagtail.embeds.blocks.EmbedBlock(
+                            help_text="Insert an embed URL e.g https://www.youtube.com/embed/SGJFWirQ3ks",
+                            icon="fa-s15",
+                            template="blocks/embed_block.html",
+                        ),
+                    ),
+                ],
+                blank=True,
+                use_json_field=True,
+                verbose_name="Page body",
+            ),
         ),
         ),
         migrations.AlterField(
         migrations.AlterField(
-            model_name='homepage',
-            name='body',
-            field=wagtail.fields.StreamField([('heading_block', wagtail.blocks.StructBlock([('heading_text', wagtail.blocks.CharBlock(form_classname='title', required=True)), ('size', wagtail.blocks.ChoiceBlock(blank=True, choices=[('', 'Select a header size'), ('h2', 'H2'), ('h3', 'H3'), ('h4', 'H4')], required=False))])), ('paragraph_block', wagtail.blocks.RichTextBlock(icon='fa-paragraph', template='blocks/paragraph_block.html')), ('image_block', wagtail.blocks.StructBlock([('image', wagtail.images.blocks.ImageChooserBlock(required=True)), ('caption', wagtail.blocks.CharBlock(required=False)), ('attribution', wagtail.blocks.CharBlock(required=False))])), ('block_quote', wagtail.blocks.StructBlock([('text', wagtail.blocks.TextBlock()), ('attribute_name', wagtail.blocks.CharBlock(blank=True, label='e.g. Mary Berry', required=False))])), ('embed_block', wagtail.embeds.blocks.EmbedBlock(help_text='Insert an embed URL e.g https://www.youtube.com/embed/SGJFWirQ3ks', icon='fa-s15', template='blocks/embed_block.html'))], blank=True, use_json_field=True, verbose_name='Home content block'),
+            model_name="homepage",
+            name="body",
+            field=wagtail.fields.StreamField(
+                [
+                    (
+                        "heading_block",
+                        wagtail.blocks.StructBlock(
+                            [
+                                (
+                                    "heading_text",
+                                    wagtail.blocks.CharBlock(
+                                        form_classname="title", required=True
+                                    ),
+                                ),
+                                (
+                                    "size",
+                                    wagtail.blocks.ChoiceBlock(
+                                        blank=True,
+                                        choices=[
+                                            ("", "Select a header size"),
+                                            ("h2", "H2"),
+                                            ("h3", "H3"),
+                                            ("h4", "H4"),
+                                        ],
+                                        required=False,
+                                    ),
+                                ),
+                            ]
+                        ),
+                    ),
+                    (
+                        "paragraph_block",
+                        wagtail.blocks.RichTextBlock(
+                            icon="fa-paragraph", template="blocks/paragraph_block.html"
+                        ),
+                    ),
+                    (
+                        "image_block",
+                        wagtail.blocks.StructBlock(
+                            [
+                                (
+                                    "image",
+                                    wagtail.images.blocks.ImageChooserBlock(
+                                        required=True
+                                    ),
+                                ),
+                                ("caption", wagtail.blocks.CharBlock(required=False)),
+                                (
+                                    "attribution",
+                                    wagtail.blocks.CharBlock(required=False),
+                                ),
+                            ]
+                        ),
+                    ),
+                    (
+                        "block_quote",
+                        wagtail.blocks.StructBlock(
+                            [
+                                ("text", wagtail.blocks.TextBlock()),
+                                (
+                                    "attribute_name",
+                                    wagtail.blocks.CharBlock(
+                                        blank=True,
+                                        label="e.g. Mary Berry",
+                                        required=False,
+                                    ),
+                                ),
+                            ]
+                        ),
+                    ),
+                    (
+                        "embed_block",
+                        wagtail.embeds.blocks.EmbedBlock(
+                            help_text="Insert an embed URL e.g https://www.youtube.com/embed/SGJFWirQ3ks",
+                            icon="fa-s15",
+                            template="blocks/embed_block.html",
+                        ),
+                    ),
+                ],
+                blank=True,
+                use_json_field=True,
+                verbose_name="Home content block",
+            ),
         ),
         ),
         migrations.AlterField(
         migrations.AlterField(
-            model_name='standardpage',
-            name='body',
-            field=wagtail.fields.StreamField([('heading_block', wagtail.blocks.StructBlock([('heading_text', wagtail.blocks.CharBlock(form_classname='title', required=True)), ('size', wagtail.blocks.ChoiceBlock(blank=True, choices=[('', 'Select a header size'), ('h2', 'H2'), ('h3', 'H3'), ('h4', 'H4')], required=False))])), ('paragraph_block', wagtail.blocks.RichTextBlock(icon='fa-paragraph', template='blocks/paragraph_block.html')), ('image_block', wagtail.blocks.StructBlock([('image', wagtail.images.blocks.ImageChooserBlock(required=True)), ('caption', wagtail.blocks.CharBlock(required=False)), ('attribution', wagtail.blocks.CharBlock(required=False))])), ('block_quote', wagtail.blocks.StructBlock([('text', wagtail.blocks.TextBlock()), ('attribute_name', wagtail.blocks.CharBlock(blank=True, label='e.g. Mary Berry', required=False))])), ('embed_block', wagtail.embeds.blocks.EmbedBlock(help_text='Insert an embed URL e.g https://www.youtube.com/embed/SGJFWirQ3ks', icon='fa-s15', template='blocks/embed_block.html'))], blank=True, use_json_field=True, verbose_name='Page body'),
+            model_name="standardpage",
+            name="body",
+            field=wagtail.fields.StreamField(
+                [
+                    (
+                        "heading_block",
+                        wagtail.blocks.StructBlock(
+                            [
+                                (
+                                    "heading_text",
+                                    wagtail.blocks.CharBlock(
+                                        form_classname="title", required=True
+                                    ),
+                                ),
+                                (
+                                    "size",
+                                    wagtail.blocks.ChoiceBlock(
+                                        blank=True,
+                                        choices=[
+                                            ("", "Select a header size"),
+                                            ("h2", "H2"),
+                                            ("h3", "H3"),
+                                            ("h4", "H4"),
+                                        ],
+                                        required=False,
+                                    ),
+                                ),
+                            ]
+                        ),
+                    ),
+                    (
+                        "paragraph_block",
+                        wagtail.blocks.RichTextBlock(
+                            icon="fa-paragraph", template="blocks/paragraph_block.html"
+                        ),
+                    ),
+                    (
+                        "image_block",
+                        wagtail.blocks.StructBlock(
+                            [
+                                (
+                                    "image",
+                                    wagtail.images.blocks.ImageChooserBlock(
+                                        required=True
+                                    ),
+                                ),
+                                ("caption", wagtail.blocks.CharBlock(required=False)),
+                                (
+                                    "attribution",
+                                    wagtail.blocks.CharBlock(required=False),
+                                ),
+                            ]
+                        ),
+                    ),
+                    (
+                        "block_quote",
+                        wagtail.blocks.StructBlock(
+                            [
+                                ("text", wagtail.blocks.TextBlock()),
+                                (
+                                    "attribute_name",
+                                    wagtail.blocks.CharBlock(
+                                        blank=True,
+                                        label="e.g. Mary Berry",
+                                        required=False,
+                                    ),
+                                ),
+                            ]
+                        ),
+                    ),
+                    (
+                        "embed_block",
+                        wagtail.embeds.blocks.EmbedBlock(
+                            help_text="Insert an embed URL e.g https://www.youtube.com/embed/SGJFWirQ3ks",
+                            icon="fa-s15",
+                            template="blocks/embed_block.html",
+                        ),
+                    ),
+                ],
+                blank=True,
+                use_json_field=True,
+                verbose_name="Page body",
+            ),
         ),
         ),
     ]
     ]

+ 146 - 128
bakerydemo/base/models.py

@@ -34,32 +34,38 @@ class People(index.Indexed, ClusterableModel):
     to the database.
     to the database.
     https://github.com/wagtail/django-modelcluster
     https://github.com/wagtail/django-modelcluster
     """
     """
+
     first_name = models.CharField("First name", max_length=254)
     first_name = models.CharField("First name", max_length=254)
     last_name = models.CharField("Last name", max_length=254)
     last_name = models.CharField("Last name", max_length=254)
     job_title = models.CharField("Job title", max_length=254)
     job_title = models.CharField("Job title", max_length=254)
 
 
     image = models.ForeignKey(
     image = models.ForeignKey(
-        'wagtailimages.Image',
+        "wagtailimages.Image",
         null=True,
         null=True,
         blank=True,
         blank=True,
         on_delete=models.SET_NULL,
         on_delete=models.SET_NULL,
-        related_name='+'
+        related_name="+",
     )
     )
 
 
     panels = [
     panels = [
-        MultiFieldPanel([
-            FieldRowPanel([
-                FieldPanel('first_name', classname="col6"),
-                FieldPanel('last_name', classname="col6"),
-            ])
-        ], "Name"),
-        FieldPanel('job_title'),
-        FieldPanel('image')
+        MultiFieldPanel(
+            [
+                FieldRowPanel(
+                    [
+                        FieldPanel("first_name", classname="col6"),
+                        FieldPanel("last_name", classname="col6"),
+                    ]
+                )
+            ],
+            "Name",
+        ),
+        FieldPanel("job_title"),
+        FieldPanel("image"),
     ]
     ]
 
 
     search_fields = [
     search_fields = [
-        index.SearchField('first_name'),
-        index.SearchField('last_name'),
+        index.SearchField("first_name"),
+        index.SearchField("last_name"),
     ]
     ]
 
 
     @property
     @property
@@ -67,16 +73,16 @@ class People(index.Indexed, ClusterableModel):
         # Returns an empty string if there is no profile pic or the rendition
         # Returns an empty string if there is no profile pic or the rendition
         # file can't be found.
         # file can't be found.
         try:
         try:
-            return self.image.get_rendition('fill-50x50').img_tag()
+            return self.image.get_rendition("fill-50x50").img_tag()
         except:  # noqa: E722 FIXME: remove bare 'except:'
         except:  # noqa: E722 FIXME: remove bare 'except:'
-            return ''
+            return ""
 
 
     def __str__(self):
     def __str__(self):
-        return '{} {}'.format(self.first_name, self.last_name)
+        return "{} {}".format(self.first_name, self.last_name)
 
 
     class Meta:
     class Meta:
-        verbose_name = 'Person'
-        verbose_name_plural = 'People'
+        verbose_name = "Person"
+        verbose_name_plural = "People"
 
 
 
 
 @register_snippet
 @register_snippet
@@ -87,17 +93,18 @@ class FooterText(models.Model):
     accessible on the template via a template tag defined in base/templatetags/
     accessible on the template via a template tag defined in base/templatetags/
     navigation_tags.py
     navigation_tags.py
     """
     """
+
     body = RichTextField()
     body = RichTextField()
 
 
     panels = [
     panels = [
-        FieldPanel('body'),
+        FieldPanel("body"),
     ]
     ]
 
 
     def __str__(self):
     def __str__(self):
         return "Footer text"
         return "Footer text"
 
 
     class Meta:
     class Meta:
-        verbose_name_plural = 'Footer Text'
+        verbose_name_plural = "Footer Text"
 
 
 
 
 class StandardPage(Page):
 class StandardPage(Page):
@@ -107,24 +114,22 @@ class StandardPage(Page):
     image, introduction and body field
     image, introduction and body field
     """
     """
 
 
-    introduction = models.TextField(
-        help_text='Text to describe the page',
-        blank=True)
+    introduction = models.TextField(help_text="Text to describe the page", blank=True)
     image = models.ForeignKey(
     image = models.ForeignKey(
-        'wagtailimages.Image',
+        "wagtailimages.Image",
         null=True,
         null=True,
         blank=True,
         blank=True,
         on_delete=models.SET_NULL,
         on_delete=models.SET_NULL,
-        related_name='+',
-        help_text='Landscape mode only; horizontal width between 1000px and 3000px.'
+        related_name="+",
+        help_text="Landscape mode only; horizontal width between 1000px and 3000px.",
     )
     )
     body = StreamField(
     body = StreamField(
         BaseStreamBlock(), verbose_name="Page body", blank=True, use_json_field=True
         BaseStreamBlock(), verbose_name="Page body", blank=True, use_json_field=True
     )
     )
     content_panels = Page.content_panels + [
     content_panels = Page.content_panels + [
-        FieldPanel('introduction', classname="full"),
-        FieldPanel('body'),
-        FieldPanel('image'),
+        FieldPanel("introduction", classname="full"),
+        FieldPanel("body"),
+        FieldPanel("image"),
     ]
     ]
 
 
 
 
@@ -141,55 +146,53 @@ class HomePage(Page):
 
 
     # Hero section of HomePage
     # Hero section of HomePage
     image = models.ForeignKey(
     image = models.ForeignKey(
-        'wagtailimages.Image',
+        "wagtailimages.Image",
         null=True,
         null=True,
         blank=True,
         blank=True,
         on_delete=models.SET_NULL,
         on_delete=models.SET_NULL,
-        related_name='+',
-        help_text='Homepage image'
+        related_name="+",
+        help_text="Homepage image",
     )
     )
     hero_text = models.CharField(
     hero_text = models.CharField(
-        max_length=255,
-        help_text='Write an introduction for the bakery'
+        max_length=255, help_text="Write an introduction for the bakery"
     )
     )
     hero_cta = models.CharField(
     hero_cta = models.CharField(
-        verbose_name='Hero CTA',
+        verbose_name="Hero CTA",
         max_length=255,
         max_length=255,
-        help_text='Text to display on Call to Action'
+        help_text="Text to display on Call to Action",
     )
     )
     hero_cta_link = models.ForeignKey(
     hero_cta_link = models.ForeignKey(
-        'wagtailcore.Page',
+        "wagtailcore.Page",
         null=True,
         null=True,
         blank=True,
         blank=True,
         on_delete=models.SET_NULL,
         on_delete=models.SET_NULL,
-        related_name='+',
-        verbose_name='Hero CTA link',
-        help_text='Choose a page to link to for the Call to Action'
+        related_name="+",
+        verbose_name="Hero CTA link",
+        help_text="Choose a page to link to for the Call to Action",
     )
     )
 
 
     # Body section of the HomePage
     # Body section of the HomePage
     body = StreamField(
     body = StreamField(
-        BaseStreamBlock(), verbose_name="Home content block", blank=True, use_json_field=True
+        BaseStreamBlock(),
+        verbose_name="Home content block",
+        blank=True,
+        use_json_field=True,
     )
     )
 
 
     # Promo section of the HomePage
     # Promo section of the HomePage
     promo_image = models.ForeignKey(
     promo_image = models.ForeignKey(
-        'wagtailimages.Image',
+        "wagtailimages.Image",
         null=True,
         null=True,
         blank=True,
         blank=True,
         on_delete=models.SET_NULL,
         on_delete=models.SET_NULL,
-        related_name='+',
-        help_text='Promo image'
+        related_name="+",
+        help_text="Promo image",
     )
     )
     promo_title = models.CharField(
     promo_title = models.CharField(
-        blank=True,
-        max_length=255,
-        help_text='Title to display above the promo copy'
+        blank=True, max_length=255, help_text="Title to display above the promo copy"
     )
     )
     promo_text = RichTextField(
     promo_text = RichTextField(
-        null=True,
-        blank=True,
-        help_text='Write some promotional copy'
+        null=True, blank=True, help_text="Write some promotional copy"
     )
     )
 
 
     # Featured sections on the HomePage
     # Featured sections on the HomePage
@@ -198,82 +201,94 @@ class HomePage(Page):
     # Each list their children items that we access via the children function
     # Each list their children items that we access via the children function
     # that we define on the individual Page models e.g. BlogIndexPage
     # that we define on the individual Page models e.g. BlogIndexPage
     featured_section_1_title = models.CharField(
     featured_section_1_title = models.CharField(
-        blank=True,
-        max_length=255,
-        help_text='Title to display above the promo copy'
+        blank=True, max_length=255, help_text="Title to display above the promo copy"
     )
     )
     featured_section_1 = models.ForeignKey(
     featured_section_1 = models.ForeignKey(
-        'wagtailcore.Page',
+        "wagtailcore.Page",
         null=True,
         null=True,
         blank=True,
         blank=True,
         on_delete=models.SET_NULL,
         on_delete=models.SET_NULL,
-        related_name='+',
-        help_text='First featured section for the homepage. Will display up to '
-        'three child items.',
-        verbose_name='Featured section 1'
+        related_name="+",
+        help_text="First featured section for the homepage. Will display up to "
+        "three child items.",
+        verbose_name="Featured section 1",
     )
     )
 
 
     featured_section_2_title = models.CharField(
     featured_section_2_title = models.CharField(
-        blank=True,
-        max_length=255,
-        help_text='Title to display above the promo copy'
+        blank=True, max_length=255, help_text="Title to display above the promo copy"
     )
     )
     featured_section_2 = models.ForeignKey(
     featured_section_2 = models.ForeignKey(
-        'wagtailcore.Page',
+        "wagtailcore.Page",
         null=True,
         null=True,
         blank=True,
         blank=True,
         on_delete=models.SET_NULL,
         on_delete=models.SET_NULL,
-        related_name='+',
-        help_text='Second featured section for the homepage. Will display up to '
-        'three child items.',
-        verbose_name='Featured section 2'
+        related_name="+",
+        help_text="Second featured section for the homepage. Will display up to "
+        "three child items.",
+        verbose_name="Featured section 2",
     )
     )
 
 
     featured_section_3_title = models.CharField(
     featured_section_3_title = models.CharField(
-        blank=True,
-        max_length=255,
-        help_text='Title to display above the promo copy'
+        blank=True, max_length=255, help_text="Title to display above the promo copy"
     )
     )
     featured_section_3 = models.ForeignKey(
     featured_section_3 = models.ForeignKey(
-        'wagtailcore.Page',
+        "wagtailcore.Page",
         null=True,
         null=True,
         blank=True,
         blank=True,
         on_delete=models.SET_NULL,
         on_delete=models.SET_NULL,
-        related_name='+',
-        help_text='Third featured section for the homepage. Will display up to '
-        'six child items.',
-        verbose_name='Featured section 3'
+        related_name="+",
+        help_text="Third featured section for the homepage. Will display up to "
+        "six child items.",
+        verbose_name="Featured section 3",
     )
     )
 
 
     content_panels = Page.content_panels + [
     content_panels = Page.content_panels + [
-        MultiFieldPanel([
-            FieldPanel('image'),
-            FieldPanel('hero_text', classname="full"),
-            MultiFieldPanel([
-                FieldPanel('hero_cta'),
-                FieldPanel('hero_cta_link'),
-            ]),
-        ], heading="Hero section"),
-        MultiFieldPanel([
-            FieldPanel('promo_image'),
-            FieldPanel('promo_title'),
-            FieldPanel('promo_text'),
-        ], heading="Promo section"),
-        FieldPanel('body'),
-        MultiFieldPanel([
-            MultiFieldPanel([
-                FieldPanel('featured_section_1_title'),
-                FieldPanel('featured_section_1'),
-            ]),
-            MultiFieldPanel([
-                FieldPanel('featured_section_2_title'),
-                FieldPanel('featured_section_2'),
-            ]),
-            MultiFieldPanel([
-                FieldPanel('featured_section_3_title'),
-                FieldPanel('featured_section_3'),
-            ]),
-        ], heading="Featured homepage sections", classname="collapsible")
+        MultiFieldPanel(
+            [
+                FieldPanel("image"),
+                FieldPanel("hero_text", classname="full"),
+                MultiFieldPanel(
+                    [
+                        FieldPanel("hero_cta"),
+                        FieldPanel("hero_cta_link"),
+                    ]
+                ),
+            ],
+            heading="Hero section",
+        ),
+        MultiFieldPanel(
+            [
+                FieldPanel("promo_image"),
+                FieldPanel("promo_title"),
+                FieldPanel("promo_text"),
+            ],
+            heading="Promo section",
+        ),
+        FieldPanel("body"),
+        MultiFieldPanel(
+            [
+                MultiFieldPanel(
+                    [
+                        FieldPanel("featured_section_1_title"),
+                        FieldPanel("featured_section_1"),
+                    ]
+                ),
+                MultiFieldPanel(
+                    [
+                        FieldPanel("featured_section_2_title"),
+                        FieldPanel("featured_section_2"),
+                    ]
+                ),
+                MultiFieldPanel(
+                    [
+                        FieldPanel("featured_section_3_title"),
+                        FieldPanel("featured_section_3"),
+                    ]
+                ),
+            ],
+            heading="Featured homepage sections",
+            classname="collapsible",
+        ),
     ]
     ]
 
 
     def __str__(self):
     def __str__(self):
@@ -288,35 +303,32 @@ class GalleryPage(Page):
     and is intended to show the extensibility of this aspect of Wagtail
     and is intended to show the extensibility of this aspect of Wagtail
     """
     """
 
 
-    introduction = models.TextField(
-        help_text='Text to describe the page',
-        blank=True)
+    introduction = models.TextField(help_text="Text to describe the page", blank=True)
     image = models.ForeignKey(
     image = models.ForeignKey(
-        'wagtailimages.Image',
+        "wagtailimages.Image",
         null=True,
         null=True,
         blank=True,
         blank=True,
         on_delete=models.SET_NULL,
         on_delete=models.SET_NULL,
-        related_name='+',
-        help_text='Landscape mode only; horizontal width between 1000px and '
-        '3000px.'
+        related_name="+",
+        help_text="Landscape mode only; horizontal width between 1000px and " "3000px.",
     )
     )
     body = StreamField(
     body = StreamField(
         BaseStreamBlock(), verbose_name="Page body", blank=True, use_json_field=True
         BaseStreamBlock(), verbose_name="Page body", blank=True, use_json_field=True
     )
     )
     collection = models.ForeignKey(
     collection = models.ForeignKey(
         Collection,
         Collection,
-        limit_choices_to=~models.Q(name__in=['Root']),
+        limit_choices_to=~models.Q(name__in=["Root"]),
         null=True,
         null=True,
         blank=True,
         blank=True,
         on_delete=models.SET_NULL,
         on_delete=models.SET_NULL,
-        help_text='Select the image collection for this gallery.'
+        help_text="Select the image collection for this gallery.",
     )
     )
 
 
     content_panels = Page.content_panels + [
     content_panels = Page.content_panels + [
-        FieldPanel('introduction', classname="full"),
-        FieldPanel('body'),
-        FieldPanel('image'),
-        FieldPanel('collection'),
+        FieldPanel("introduction", classname="full"),
+        FieldPanel("body"),
+        FieldPanel("image"),
+        FieldPanel("collection"),
     ]
     ]
 
 
     # Defining what content type can sit under the parent. Since it's a blank
     # Defining what content type can sit under the parent. Since it's a blank
@@ -333,16 +345,17 @@ class FormField(AbstractFormField):
     can read more about Wagtail forms at:
     can read more about Wagtail forms at:
     https://docs.wagtail.org/en/stable/reference/contrib/forms/index.html
     https://docs.wagtail.org/en/stable/reference/contrib/forms/index.html
     """
     """
-    page = ParentalKey('FormPage', related_name='form_fields', on_delete=models.CASCADE)
+
+    page = ParentalKey("FormPage", related_name="form_fields", on_delete=models.CASCADE)
 
 
 
 
 class FormPage(AbstractEmailForm):
 class FormPage(AbstractEmailForm):
     image = models.ForeignKey(
     image = models.ForeignKey(
-        'wagtailimages.Image',
+        "wagtailimages.Image",
         null=True,
         null=True,
         blank=True,
         blank=True,
         on_delete=models.SET_NULL,
         on_delete=models.SET_NULL,
-        related_name='+'
+        related_name="+",
     )
     )
     body = StreamField(BaseStreamBlock(), use_json_field=True)
     body = StreamField(BaseStreamBlock(), use_json_field=True)
     thank_you_text = RichTextField(blank=True)
     thank_you_text = RichTextField(blank=True)
@@ -350,15 +363,20 @@ class FormPage(AbstractEmailForm):
     # Note how we include the FormField object via an InlinePanel using the
     # Note how we include the FormField object via an InlinePanel using the
     # related_name value
     # related_name value
     content_panels = AbstractEmailForm.content_panels + [
     content_panels = AbstractEmailForm.content_panels + [
-        FieldPanel('image'),
-        FieldPanel('body'),
-        InlinePanel('form_fields', label="Form fields"),
-        FieldPanel('thank_you_text', classname="full"),
-        MultiFieldPanel([
-            FieldRowPanel([
-                FieldPanel('from_address', classname="col6"),
-                FieldPanel('to_address', classname="col6"),
-            ]),
-            FieldPanel('subject'),
-        ], "Email"),
+        FieldPanel("image"),
+        FieldPanel("body"),
+        InlinePanel("form_fields", label="Form fields"),
+        FieldPanel("thank_you_text", classname="full"),
+        MultiFieldPanel(
+            [
+                FieldRowPanel(
+                    [
+                        FieldPanel("from_address", classname="col6"),
+                        FieldPanel("to_address", classname="col6"),
+                    ]
+                ),
+                FieldPanel("subject"),
+            ],
+            "Email",
+        ),
     ]
     ]

+ 3 - 3
bakerydemo/base/templatetags/gallery_tags.py

@@ -6,11 +6,11 @@ register = template.Library()
 
 
 
 
 # Retrieves a single gallery item and returns a gallery of images
 # Retrieves a single gallery item and returns a gallery of images
-@register.inclusion_tag('tags/gallery.html', takes_context=True)
+@register.inclusion_tag("tags/gallery.html", takes_context=True)
 def gallery(context, gallery):
 def gallery(context, gallery):
     images = Image.objects.filter(collection=gallery)
     images = Image.objects.filter(collection=gallery)
 
 
     return {
     return {
-        'images': images,
-        'request': context['request'],
+        "images": images,
+        "request": context["request"],
     }
     }

+ 27 - 22
bakerydemo/base/templatetags/navigation_tags.py

@@ -14,7 +14,7 @@ def get_site_root(context):
     # This returns a core.Page. The main menu needs to have the site.root_page
     # This returns a core.Page. The main menu needs to have the site.root_page
     # defined else will return an object attribute error ('str' object has no
     # defined else will return an object attribute error ('str' object has no
     # attribute 'get_children')
     # attribute 'get_children')
-    return Site.find_for_request(context['request']).root_page
+    return Site.find_for_request(context["request"]).root_page
 
 
 
 
 def has_menu_children(page):
 def has_menu_children(page):
@@ -31,13 +31,13 @@ def has_children(page):
 
 
 def is_active(page, current_page):
 def is_active(page, current_page):
     # To give us active state on main navigation
     # To give us active state on main navigation
-    return (current_page.url_path.startswith(page.url_path) if current_page else False)
+    return current_page.url_path.startswith(page.url_path) if current_page else False
 
 
 
 
 # Retrieves the top menu items - the immediate children of the parent page
 # Retrieves the top menu items - the immediate children of the parent page
 # The has_menu_children method is necessary because the Foundation menu requires
 # The has_menu_children method is necessary because the Foundation menu requires
 # a dropdown class to be applied to a parent
 # a dropdown class to be applied to a parent
-@register.inclusion_tag('tags/top_menu.html', takes_context=True)
+@register.inclusion_tag("tags/top_menu.html", takes_context=True)
 def top_menu(context, parent, calling_page=None):
 def top_menu(context, parent, calling_page=None):
     menuitems = parent.get_children().live().in_menu()
     menuitems = parent.get_children().live().in_menu()
     for menuitem in menuitems:
     for menuitem in menuitems:
@@ -45,18 +45,21 @@ def top_menu(context, parent, calling_page=None):
         # We don't directly check if calling_page is None since the template
         # We don't directly check if calling_page is None since the template
         # engine can pass an empty string to calling_page
         # engine can pass an empty string to calling_page
         # if the variable passed as calling_page does not exist.
         # if the variable passed as calling_page does not exist.
-        menuitem.active = (calling_page.url_path.startswith(menuitem.url_path)
-                           if calling_page else False)
+        menuitem.active = (
+            calling_page.url_path.startswith(menuitem.url_path)
+            if calling_page
+            else False
+        )
     return {
     return {
-        'calling_page': calling_page,
-        'menuitems': menuitems,
+        "calling_page": calling_page,
+        "menuitems": menuitems,
         # required by the pageurl tag that we want to use within this template
         # required by the pageurl tag that we want to use within this template
-        'request': context['request'],
+        "request": context["request"],
     }
     }
 
 
 
 
 # Retrieves the children of the top menu items for the drop downs
 # Retrieves the children of the top menu items for the drop downs
-@register.inclusion_tag('tags/top_menu_children.html', takes_context=True)
+@register.inclusion_tag("tags/top_menu_children.html", takes_context=True)
 def top_menu_children(context, parent, calling_page=None):
 def top_menu_children(context, parent, calling_page=None):
     menuitems_children = parent.get_children()
     menuitems_children = parent.get_children()
     menuitems_children = menuitems_children.live().in_menu()
     menuitems_children = menuitems_children.live().in_menu()
@@ -65,38 +68,40 @@ def top_menu_children(context, parent, calling_page=None):
         # We don't directly check if calling_page is None since the template
         # We don't directly check if calling_page is None since the template
         # engine can pass an empty string to calling_page
         # engine can pass an empty string to calling_page
         # if the variable passed as calling_page does not exist.
         # if the variable passed as calling_page does not exist.
-        menuitem.active = (calling_page.url_path.startswith(menuitem.url_path)
-                           if calling_page else False)
+        menuitem.active = (
+            calling_page.url_path.startswith(menuitem.url_path)
+            if calling_page
+            else False
+        )
         menuitem.children = menuitem.get_children().live().in_menu()
         menuitem.children = menuitem.get_children().live().in_menu()
     return {
     return {
-        'parent': parent,
-        'menuitems_children': menuitems_children,
+        "parent": parent,
+        "menuitems_children": menuitems_children,
         # required by the pageurl tag that we want to use within this template
         # required by the pageurl tag that we want to use within this template
-        'request': context['request'],
+        "request": context["request"],
     }
     }
 
 
 
 
-@register.inclusion_tag('tags/breadcrumbs.html', takes_context=True)
+@register.inclusion_tag("tags/breadcrumbs.html", takes_context=True)
 def breadcrumbs(context):
 def breadcrumbs(context):
-    self = context.get('self')
+    self = context.get("self")
     if self is None or self.depth <= 2:
     if self is None or self.depth <= 2:
         # When on the home page, displaying breadcrumbs is irrelevant.
         # When on the home page, displaying breadcrumbs is irrelevant.
         ancestors = ()
         ancestors = ()
     else:
     else:
-        ancestors = Page.objects.ancestor_of(
-            self, inclusive=True).filter(depth__gt=1)
+        ancestors = Page.objects.ancestor_of(self, inclusive=True).filter(depth__gt=1)
     return {
     return {
-        'ancestors': ancestors,
-        'request': context['request'],
+        "ancestors": ancestors,
+        "request": context["request"],
     }
     }
 
 
 
 
-@register.inclusion_tag('base/include/footer_text.html', takes_context=True)
+@register.inclusion_tag("base/include/footer_text.html", takes_context=True)
 def get_footer_text(context):
 def get_footer_text(context):
     footer_text = ""
     footer_text = ""
     if FooterText.objects.first() is not None:
     if FooterText.objects.first() is not None:
         footer_text = FooterText.objects.first().body
         footer_text = FooterText.objects.first().body
 
 
     return {
     return {
-        'footer_text': footer_text,
+        "footer_text": footer_text,
     }
     }

+ 19 - 16
bakerydemo/base/wagtail_hooks.py

@@ -1,10 +1,13 @@
 from wagtail.contrib.modeladmin.options import (
 from wagtail.contrib.modeladmin.options import (
-    ModelAdmin, ModelAdminGroup, modeladmin_register)
+    ModelAdmin,
+    ModelAdminGroup,
+    modeladmin_register,
+)
 
 
 from bakerydemo.breads.models import Country, BreadIngredient, BreadType
 from bakerydemo.breads.models import Country, BreadIngredient, BreadType
 from bakerydemo.base.models import People, FooterText
 from bakerydemo.base.models import People, FooterText
 
 
-'''
+"""
 N.B. To see what icons are available for use in Wagtail menus and StreamField block types,
 N.B. To see what icons are available for use in Wagtail menus and StreamField block types,
 enable the styleguide in settings:
 enable the styleguide in settings:
 
 
@@ -18,51 +21,51 @@ or see https://thegrouchy.dev/general/2015/12/06/wagtail-streamfield-icons.html
 
 
 This demo project includes the full font-awesome set via CDN in base.html, so the entire
 This demo project includes the full font-awesome set via CDN in base.html, so the entire
 font-awesome icon set is available to you. Options are at https://fontawesome.com/icons .
 font-awesome icon set is available to you. Options are at https://fontawesome.com/icons .
-'''
+"""
 
 
 
 
 class BreadIngredientAdmin(ModelAdmin):
 class BreadIngredientAdmin(ModelAdmin):
     # These stub classes allow us to put various models into the custom "Wagtail Bakery" menu item
     # These stub classes allow us to put various models into the custom "Wagtail Bakery" menu item
     # rather than under the default Snippets section.
     # rather than under the default Snippets section.
     model = BreadIngredient
     model = BreadIngredient
-    search_fields = ('name', )
+    search_fields = ("name",)
 
 
 
 
 class BreadTypeAdmin(ModelAdmin):
 class BreadTypeAdmin(ModelAdmin):
     model = BreadType
     model = BreadType
-    search_fields = ('title', )
+    search_fields = ("title",)
 
 
 
 
 class BreadCountryAdmin(ModelAdmin):
 class BreadCountryAdmin(ModelAdmin):
     model = Country
     model = Country
-    search_fields = ('title', )
+    search_fields = ("title",)
 
 
 
 
 class BreadModelAdminGroup(ModelAdminGroup):
 class BreadModelAdminGroup(ModelAdminGroup):
-    menu_label = 'Bread Categories'
-    menu_icon = 'fa-suitcase'  # change as required
+    menu_label = "Bread Categories"
+    menu_icon = "fa-suitcase"  # change as required
     menu_order = 200  # will put in 3rd place (000 being 1st, 100 2nd)
     menu_order = 200  # will put in 3rd place (000 being 1st, 100 2nd)
     items = (BreadIngredientAdmin, BreadTypeAdmin, BreadCountryAdmin)
     items = (BreadIngredientAdmin, BreadTypeAdmin, BreadCountryAdmin)
 
 
 
 
 class PeopleModelAdmin(ModelAdmin):
 class PeopleModelAdmin(ModelAdmin):
     model = People
     model = People
-    menu_label = 'People'  # ditch this to use verbose_name_plural from model
-    menu_icon = 'fa-users'  # change as required
-    list_display = ('first_name', 'last_name', 'job_title', 'thumb_image')
-    list_filter = ('job_title', )
-    search_fields = ('first_name', 'last_name', 'job_title')
+    menu_label = "People"  # ditch this to use verbose_name_plural from model
+    menu_icon = "fa-users"  # change as required
+    list_display = ("first_name", "last_name", "job_title", "thumb_image")
+    list_filter = ("job_title",)
+    search_fields = ("first_name", "last_name", "job_title")
     inspect_view_enabled = True
     inspect_view_enabled = True
 
 
 
 
 class FooterTextAdmin(ModelAdmin):
 class FooterTextAdmin(ModelAdmin):
     model = FooterText
     model = FooterText
-    search_fields = ('body',)
+    search_fields = ("body",)
 
 
 
 
 class BakeryModelAdminGroup(ModelAdminGroup):
 class BakeryModelAdminGroup(ModelAdminGroup):
-    menu_label = 'Bakery Misc'
-    menu_icon = 'fa-cutlery'  # change as required
+    menu_label = "Bakery Misc"
+    menu_icon = "fa-cutlery"  # change as required
     menu_order = 300  # will put in 4th place (000 being 1st, 100 2nd)
     menu_order = 300  # will put in 4th place (000 being 1st, 100 2nd)
     items = (PeopleModelAdmin, FooterTextAdmin)
     items = (PeopleModelAdmin, FooterTextAdmin)
 
 

+ 315 - 35
bakerydemo/blog/migrations/0001_initial.py

@@ -18,68 +18,348 @@ class Migration(migrations.Migration):
     initial = True
     initial = True
 
 
     dependencies = [
     dependencies = [
-        ('taggit', '0002_auto_20150616_2121'),
-        ('wagtailcore', '0032_add_bulk_delete_page_permission'),
-        ('base', '0001_initial'),
-        ('wagtailimages', '0018_remove_rendition_filter'),
+        ("taggit", "0002_auto_20150616_2121"),
+        ("wagtailcore", "0032_add_bulk_delete_page_permission"),
+        ("base", "0001_initial"),
+        ("wagtailimages", "0018_remove_rendition_filter"),
     ]
     ]
 
 
     operations = [
     operations = [
         migrations.CreateModel(
         migrations.CreateModel(
-            name='BlogIndexPage',
+            name="BlogIndexPage",
             fields=[
             fields=[
-                ('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.Page')),
-                ('introduction', models.TextField(blank=True, help_text='Text to describe the page')),
-                ('body', wagtail.fields.StreamField((('heading_block', wagtail.blocks.StructBlock((('heading_text', wagtail.blocks.CharBlock(classname='title', required=True)), ('size', wagtail.blocks.ChoiceBlock(blank=True, choices=[('', 'Select a header size'), ('h2', 'H2'), ('h3', 'H3'), ('h4', 'H4')], required=False))))), ('paragraph_block', wagtail.blocks.RichTextBlock(icon='fa-paragraph', template='blocks/paragraph_block.html')), ('image_block', wagtail.blocks.StructBlock((('image', wagtail.images.blocks.ImageChooserBlock(required=True)), ('caption', wagtail.blocks.CharBlock(required=False)), ('attribution', wagtail.blocks.CharBlock(required=False))))), ('block_quote', wagtail.blocks.StructBlock((('text', wagtail.blocks.TextBlock()), ('attribute_name', wagtail.blocks.CharBlock(blank=True, label='e.g. Guy Picciotto', required=False))))), ('embed_block', wagtail.embeds.blocks.EmbedBlock(help_text='Insert an embed URL e.g https://www.youtube.com/embed/SGJFWirQ3ks', icon='fa-s15', template='blocks/embed_block.html'))), blank=True, verbose_name='Page body')),
-                ('image', models.ForeignKey(blank=True, help_text='Landscape mode only; horizontal width between 1000px and 3000px.', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailimages.Image')),
+                (
+                    "page_ptr",
+                    models.OneToOneField(
+                        auto_created=True,
+                        on_delete=django.db.models.deletion.CASCADE,
+                        parent_link=True,
+                        primary_key=True,
+                        serialize=False,
+                        to="wagtailcore.Page",
+                    ),
+                ),
+                (
+                    "introduction",
+                    models.TextField(blank=True, help_text="Text to describe the page"),
+                ),
+                (
+                    "body",
+                    wagtail.fields.StreamField(
+                        (
+                            (
+                                "heading_block",
+                                wagtail.blocks.StructBlock(
+                                    (
+                                        (
+                                            "heading_text",
+                                            wagtail.blocks.CharBlock(
+                                                classname="title", required=True
+                                            ),
+                                        ),
+                                        (
+                                            "size",
+                                            wagtail.blocks.ChoiceBlock(
+                                                blank=True,
+                                                choices=[
+                                                    ("", "Select a header size"),
+                                                    ("h2", "H2"),
+                                                    ("h3", "H3"),
+                                                    ("h4", "H4"),
+                                                ],
+                                                required=False,
+                                            ),
+                                        ),
+                                    )
+                                ),
+                            ),
+                            (
+                                "paragraph_block",
+                                wagtail.blocks.RichTextBlock(
+                                    icon="fa-paragraph",
+                                    template="blocks/paragraph_block.html",
+                                ),
+                            ),
+                            (
+                                "image_block",
+                                wagtail.blocks.StructBlock(
+                                    (
+                                        (
+                                            "image",
+                                            wagtail.images.blocks.ImageChooserBlock(
+                                                required=True
+                                            ),
+                                        ),
+                                        (
+                                            "caption",
+                                            wagtail.blocks.CharBlock(required=False),
+                                        ),
+                                        (
+                                            "attribution",
+                                            wagtail.blocks.CharBlock(required=False),
+                                        ),
+                                    )
+                                ),
+                            ),
+                            (
+                                "block_quote",
+                                wagtail.blocks.StructBlock(
+                                    (
+                                        ("text", wagtail.blocks.TextBlock()),
+                                        (
+                                            "attribute_name",
+                                            wagtail.blocks.CharBlock(
+                                                blank=True,
+                                                label="e.g. Guy Picciotto",
+                                                required=False,
+                                            ),
+                                        ),
+                                    )
+                                ),
+                            ),
+                            (
+                                "embed_block",
+                                wagtail.embeds.blocks.EmbedBlock(
+                                    help_text="Insert an embed URL e.g https://www.youtube.com/embed/SGJFWirQ3ks",
+                                    icon="fa-s15",
+                                    template="blocks/embed_block.html",
+                                ),
+                            ),
+                        ),
+                        blank=True,
+                        verbose_name="Page body",
+                    ),
+                ),
+                (
+                    "image",
+                    models.ForeignKey(
+                        blank=True,
+                        help_text="Landscape mode only; horizontal width between 1000px and 3000px.",
+                        null=True,
+                        on_delete=django.db.models.deletion.SET_NULL,
+                        related_name="+",
+                        to="wagtailimages.Image",
+                    ),
+                ),
             ],
             ],
             options={
             options={
-                'abstract': False,
+                "abstract": False,
             },
             },
-            bases=(wagtail.contrib.routable_page.models.RoutablePageMixin, 'wagtailcore.page', models.Model),
+            bases=(
+                wagtail.contrib.routable_page.models.RoutablePageMixin,
+                "wagtailcore.page",
+                models.Model,
+            ),
         ),
         ),
         migrations.CreateModel(
         migrations.CreateModel(
-            name='BlogPage',
+            name="BlogPage",
             fields=[
             fields=[
-                ('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.Page')),
-                ('introduction', models.TextField(blank=True, help_text='Text to describe the page')),
-                ('body', wagtail.fields.StreamField((('heading_block', wagtail.blocks.StructBlock((('heading_text', wagtail.blocks.CharBlock(classname='title', required=True)), ('size', wagtail.blocks.ChoiceBlock(blank=True, choices=[('', 'Select a header size'), ('h2', 'H2'), ('h3', 'H3'), ('h4', 'H4')], required=False))))), ('paragraph_block', wagtail.blocks.RichTextBlock(icon='fa-paragraph', template='blocks/paragraph_block.html')), ('image_block', wagtail.blocks.StructBlock((('image', wagtail.images.blocks.ImageChooserBlock(required=True)), ('caption', wagtail.blocks.CharBlock(required=False)), ('attribution', wagtail.blocks.CharBlock(required=False))))), ('block_quote', wagtail.blocks.StructBlock((('text', wagtail.blocks.TextBlock()), ('attribute_name', wagtail.blocks.CharBlock(blank=True, label='e.g. Guy Picciotto', required=False))))), ('embed_block', wagtail.embeds.blocks.EmbedBlock(help_text='Insert an embed URL e.g https://www.youtube.com/embed/SGJFWirQ3ks', icon='fa-s15', template='blocks/embed_block.html'))), blank=True, verbose_name='Page body')),
-                ('subtitle', models.CharField(blank=True, max_length=255)),
-                ('date_published', models.DateField(blank=True, null=True, verbose_name='Date article published')),
-                ('image', models.ForeignKey(blank=True, help_text='Landscape mode only; horizontal width between 1000px and 3000px.', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailimages.Image')),
+                (
+                    "page_ptr",
+                    models.OneToOneField(
+                        auto_created=True,
+                        on_delete=django.db.models.deletion.CASCADE,
+                        parent_link=True,
+                        primary_key=True,
+                        serialize=False,
+                        to="wagtailcore.Page",
+                    ),
+                ),
+                (
+                    "introduction",
+                    models.TextField(blank=True, help_text="Text to describe the page"),
+                ),
+                (
+                    "body",
+                    wagtail.fields.StreamField(
+                        (
+                            (
+                                "heading_block",
+                                wagtail.blocks.StructBlock(
+                                    (
+                                        (
+                                            "heading_text",
+                                            wagtail.blocks.CharBlock(
+                                                classname="title", required=True
+                                            ),
+                                        ),
+                                        (
+                                            "size",
+                                            wagtail.blocks.ChoiceBlock(
+                                                blank=True,
+                                                choices=[
+                                                    ("", "Select a header size"),
+                                                    ("h2", "H2"),
+                                                    ("h3", "H3"),
+                                                    ("h4", "H4"),
+                                                ],
+                                                required=False,
+                                            ),
+                                        ),
+                                    )
+                                ),
+                            ),
+                            (
+                                "paragraph_block",
+                                wagtail.blocks.RichTextBlock(
+                                    icon="fa-paragraph",
+                                    template="blocks/paragraph_block.html",
+                                ),
+                            ),
+                            (
+                                "image_block",
+                                wagtail.blocks.StructBlock(
+                                    (
+                                        (
+                                            "image",
+                                            wagtail.images.blocks.ImageChooserBlock(
+                                                required=True
+                                            ),
+                                        ),
+                                        (
+                                            "caption",
+                                            wagtail.blocks.CharBlock(required=False),
+                                        ),
+                                        (
+                                            "attribution",
+                                            wagtail.blocks.CharBlock(required=False),
+                                        ),
+                                    )
+                                ),
+                            ),
+                            (
+                                "block_quote",
+                                wagtail.blocks.StructBlock(
+                                    (
+                                        ("text", wagtail.blocks.TextBlock()),
+                                        (
+                                            "attribute_name",
+                                            wagtail.blocks.CharBlock(
+                                                blank=True,
+                                                label="e.g. Guy Picciotto",
+                                                required=False,
+                                            ),
+                                        ),
+                                    )
+                                ),
+                            ),
+                            (
+                                "embed_block",
+                                wagtail.embeds.blocks.EmbedBlock(
+                                    help_text="Insert an embed URL e.g https://www.youtube.com/embed/SGJFWirQ3ks",
+                                    icon="fa-s15",
+                                    template="blocks/embed_block.html",
+                                ),
+                            ),
+                        ),
+                        blank=True,
+                        verbose_name="Page body",
+                    ),
+                ),
+                ("subtitle", models.CharField(blank=True, max_length=255)),
+                (
+                    "date_published",
+                    models.DateField(
+                        blank=True, null=True, verbose_name="Date article published"
+                    ),
+                ),
+                (
+                    "image",
+                    models.ForeignKey(
+                        blank=True,
+                        help_text="Landscape mode only; horizontal width between 1000px and 3000px.",
+                        null=True,
+                        on_delete=django.db.models.deletion.SET_NULL,
+                        related_name="+",
+                        to="wagtailimages.Image",
+                    ),
+                ),
             ],
             ],
             options={
             options={
-                'abstract': False,
+                "abstract": False,
             },
             },
-            bases=('wagtailcore.page', models.Model),
+            bases=("wagtailcore.page", models.Model),
         ),
         ),
         migrations.CreateModel(
         migrations.CreateModel(
-            name='BlogPageTag',
+            name="BlogPageTag",
             fields=[
             fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('content_object', modelcluster.fields.ParentalKey(on_delete=django.db.models.deletion.CASCADE, related_name='tagged_items', to='blog.BlogPage')),
-                ('tag', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='blog_blogpagetag_items', to='taggit.Tag')),
+                (
+                    "id",
+                    models.AutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                (
+                    "content_object",
+                    modelcluster.fields.ParentalKey(
+                        on_delete=django.db.models.deletion.CASCADE,
+                        related_name="tagged_items",
+                        to="blog.BlogPage",
+                    ),
+                ),
+                (
+                    "tag",
+                    models.ForeignKey(
+                        on_delete=django.db.models.deletion.CASCADE,
+                        related_name="blog_blogpagetag_items",
+                        to="taggit.Tag",
+                    ),
+                ),
             ],
             ],
             options={
             options={
-                'abstract': False,
+                "abstract": False,
             },
             },
         ),
         ),
         migrations.CreateModel(
         migrations.CreateModel(
-            name='BlogPeopleRelationship',
+            name="BlogPeopleRelationship",
             fields=[
             fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('sort_order', models.IntegerField(blank=True, editable=False, null=True)),
-                ('page', modelcluster.fields.ParentalKey(on_delete=django.db.models.deletion.CASCADE, related_name='blog_person_relationship', to='blog.BlogPage')),
-                ('people', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='person_blog_relationship', to='base.People')),
+                (
+                    "id",
+                    models.AutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                (
+                    "sort_order",
+                    models.IntegerField(blank=True, editable=False, null=True),
+                ),
+                (
+                    "page",
+                    modelcluster.fields.ParentalKey(
+                        on_delete=django.db.models.deletion.CASCADE,
+                        related_name="blog_person_relationship",
+                        to="blog.BlogPage",
+                    ),
+                ),
+                (
+                    "people",
+                    models.ForeignKey(
+                        on_delete=django.db.models.deletion.CASCADE,
+                        related_name="person_blog_relationship",
+                        to="base.People",
+                    ),
+                ),
             ],
             ],
             options={
             options={
-                'ordering': ['sort_order'],
-                'abstract': False,
+                "ordering": ["sort_order"],
+                "abstract": False,
             },
             },
         ),
         ),
         migrations.AddField(
         migrations.AddField(
-            model_name='blogpage',
-            name='tags',
-            field=modelcluster.contrib.taggit.ClusterTaggableManager(blank=True, help_text='A comma-separated list of tags.', through='blog.BlogPageTag', to='taggit.Tag', verbose_name='Tags'),
+            model_name="blogpage",
+            name="tags",
+            field=modelcluster.contrib.taggit.ClusterTaggableManager(
+                blank=True,
+                help_text="A comma-separated list of tags.",
+                through="blog.BlogPageTag",
+                to="taggit.Tag",
+                verbose_name="Tags",
+            ),
         ),
         ),
     ]
     ]

+ 3 - 3
bakerydemo/blog/migrations/0002_remove_blogindexpage_body.py

@@ -8,12 +8,12 @@ from django.db import migrations
 class Migration(migrations.Migration):
 class Migration(migrations.Migration):
 
 
     dependencies = [
     dependencies = [
-        ('blog', '0001_initial'),
+        ("blog", "0001_initial"),
     ]
     ]
 
 
     operations = [
     operations = [
         migrations.RemoveField(
         migrations.RemoveField(
-            model_name='blogindexpage',
-            name='body',
+            model_name="blogindexpage",
+            name="body",
         ),
         ),
     ]
     ]

+ 83 - 4
bakerydemo/blog/migrations/0003_auto_20170329_0055.py

@@ -12,13 +12,92 @@ import wagtail.images.blocks
 class Migration(migrations.Migration):
 class Migration(migrations.Migration):
 
 
     dependencies = [
     dependencies = [
-        ('blog', '0002_remove_blogindexpage_body'),
+        ("blog", "0002_remove_blogindexpage_body"),
     ]
     ]
 
 
     operations = [
     operations = [
         migrations.AlterField(
         migrations.AlterField(
-            model_name='blogpage',
-            name='body',
-            field=wagtail.fields.StreamField((('heading_block', wagtail.blocks.StructBlock((('heading_text', wagtail.blocks.CharBlock(classname='title', required=True)), ('size', wagtail.blocks.ChoiceBlock(blank=True, choices=[('', 'Select a header size'), ('h2', 'H2'), ('h3', 'H3'), ('h4', 'H4')], required=False))))), ('paragraph_block', wagtail.blocks.RichTextBlock(icon='fa-paragraph', template='blocks/paragraph_block.html')), ('image_block', wagtail.blocks.StructBlock((('image', wagtail.images.blocks.ImageChooserBlock(required=True)), ('caption', wagtail.blocks.CharBlock(required=False)), ('attribution', wagtail.blocks.CharBlock(required=False))))), ('block_quote', wagtail.blocks.StructBlock((('text', wagtail.blocks.TextBlock()), ('attribute_name', wagtail.blocks.CharBlock(blank=True, label='e.g. Mary Berry', required=False))))), ('embed_block', wagtail.embeds.blocks.EmbedBlock(help_text='Insert an embed URL e.g https://www.youtube.com/embed/SGJFWirQ3ks', icon='fa-s15', template='blocks/embed_block.html'))), blank=True, verbose_name='Page body'),
+            model_name="blogpage",
+            name="body",
+            field=wagtail.fields.StreamField(
+                (
+                    (
+                        "heading_block",
+                        wagtail.blocks.StructBlock(
+                            (
+                                (
+                                    "heading_text",
+                                    wagtail.blocks.CharBlock(
+                                        classname="title", required=True
+                                    ),
+                                ),
+                                (
+                                    "size",
+                                    wagtail.blocks.ChoiceBlock(
+                                        blank=True,
+                                        choices=[
+                                            ("", "Select a header size"),
+                                            ("h2", "H2"),
+                                            ("h3", "H3"),
+                                            ("h4", "H4"),
+                                        ],
+                                        required=False,
+                                    ),
+                                ),
+                            )
+                        ),
+                    ),
+                    (
+                        "paragraph_block",
+                        wagtail.blocks.RichTextBlock(
+                            icon="fa-paragraph", template="blocks/paragraph_block.html"
+                        ),
+                    ),
+                    (
+                        "image_block",
+                        wagtail.blocks.StructBlock(
+                            (
+                                (
+                                    "image",
+                                    wagtail.images.blocks.ImageChooserBlock(
+                                        required=True
+                                    ),
+                                ),
+                                ("caption", wagtail.blocks.CharBlock(required=False)),
+                                (
+                                    "attribution",
+                                    wagtail.blocks.CharBlock(required=False),
+                                ),
+                            )
+                        ),
+                    ),
+                    (
+                        "block_quote",
+                        wagtail.blocks.StructBlock(
+                            (
+                                ("text", wagtail.blocks.TextBlock()),
+                                (
+                                    "attribute_name",
+                                    wagtail.blocks.CharBlock(
+                                        blank=True,
+                                        label="e.g. Mary Berry",
+                                        required=False,
+                                    ),
+                                ),
+                            )
+                        ),
+                    ),
+                    (
+                        "embed_block",
+                        wagtail.embeds.blocks.EmbedBlock(
+                            help_text="Insert an embed URL e.g https://www.youtube.com/embed/SGJFWirQ3ks",
+                            icon="fa-s15",
+                            template="blocks/embed_block.html",
+                        ),
+                    ),
+                ),
+                blank=True,
+                verbose_name="Page body",
+            ),
         ),
         ),
     ]
     ]

+ 9 - 5
bakerydemo/blog/migrations/0004_alter_blogpagetag_tag.py

@@ -7,14 +7,18 @@ import django.db.models.deletion
 class Migration(migrations.Migration):
 class Migration(migrations.Migration):
 
 
     dependencies = [
     dependencies = [
-        ('taggit', '0004_alter_taggeditem_content_type_alter_taggeditem_tag'),
-        ('blog', '0003_auto_20170329_0055'),
+        ("taggit", "0004_alter_taggeditem_content_type_alter_taggeditem_tag"),
+        ("blog", "0003_auto_20170329_0055"),
     ]
     ]
 
 
     operations = [
     operations = [
         migrations.AlterField(
         migrations.AlterField(
-            model_name='blogpagetag',
-            name='tag',
-            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='%(app_label)s_%(class)s_items', to='taggit.tag'),
+            model_name="blogpagetag",
+            name="tag",
+            field=models.ForeignKey(
+                on_delete=django.db.models.deletion.CASCADE,
+                related_name="%(app_label)s_%(class)s_items",
+                to="taggit.tag",
+            ),
         ),
         ),
     ]
     ]

+ 84 - 4
bakerydemo/blog/migrations/0005_use_json_field_for_body_streamfield.py

@@ -10,13 +10,93 @@ import wagtail.images.blocks
 class Migration(migrations.Migration):
 class Migration(migrations.Migration):
 
 
     dependencies = [
     dependencies = [
-        ('blog', '0004_alter_blogpagetag_tag'),
+        ("blog", "0004_alter_blogpagetag_tag"),
     ]
     ]
 
 
     operations = [
     operations = [
         migrations.AlterField(
         migrations.AlterField(
-            model_name='blogpage',
-            name='body',
-            field=wagtail.fields.StreamField([('heading_block', wagtail.blocks.StructBlock([('heading_text', wagtail.blocks.CharBlock(form_classname='title', required=True)), ('size', wagtail.blocks.ChoiceBlock(blank=True, choices=[('', 'Select a header size'), ('h2', 'H2'), ('h3', 'H3'), ('h4', 'H4')], required=False))])), ('paragraph_block', wagtail.blocks.RichTextBlock(icon='fa-paragraph', template='blocks/paragraph_block.html')), ('image_block', wagtail.blocks.StructBlock([('image', wagtail.images.blocks.ImageChooserBlock(required=True)), ('caption', wagtail.blocks.CharBlock(required=False)), ('attribution', wagtail.blocks.CharBlock(required=False))])), ('block_quote', wagtail.blocks.StructBlock([('text', wagtail.blocks.TextBlock()), ('attribute_name', wagtail.blocks.CharBlock(blank=True, label='e.g. Mary Berry', required=False))])), ('embed_block', wagtail.embeds.blocks.EmbedBlock(help_text='Insert an embed URL e.g https://www.youtube.com/embed/SGJFWirQ3ks', icon='fa-s15', template='blocks/embed_block.html'))], blank=True, use_json_field=True, verbose_name='Page body'),
+            model_name="blogpage",
+            name="body",
+            field=wagtail.fields.StreamField(
+                [
+                    (
+                        "heading_block",
+                        wagtail.blocks.StructBlock(
+                            [
+                                (
+                                    "heading_text",
+                                    wagtail.blocks.CharBlock(
+                                        form_classname="title", required=True
+                                    ),
+                                ),
+                                (
+                                    "size",
+                                    wagtail.blocks.ChoiceBlock(
+                                        blank=True,
+                                        choices=[
+                                            ("", "Select a header size"),
+                                            ("h2", "H2"),
+                                            ("h3", "H3"),
+                                            ("h4", "H4"),
+                                        ],
+                                        required=False,
+                                    ),
+                                ),
+                            ]
+                        ),
+                    ),
+                    (
+                        "paragraph_block",
+                        wagtail.blocks.RichTextBlock(
+                            icon="fa-paragraph", template="blocks/paragraph_block.html"
+                        ),
+                    ),
+                    (
+                        "image_block",
+                        wagtail.blocks.StructBlock(
+                            [
+                                (
+                                    "image",
+                                    wagtail.images.blocks.ImageChooserBlock(
+                                        required=True
+                                    ),
+                                ),
+                                ("caption", wagtail.blocks.CharBlock(required=False)),
+                                (
+                                    "attribution",
+                                    wagtail.blocks.CharBlock(required=False),
+                                ),
+                            ]
+                        ),
+                    ),
+                    (
+                        "block_quote",
+                        wagtail.blocks.StructBlock(
+                            [
+                                ("text", wagtail.blocks.TextBlock()),
+                                (
+                                    "attribute_name",
+                                    wagtail.blocks.CharBlock(
+                                        blank=True,
+                                        label="e.g. Mary Berry",
+                                        required=False,
+                                    ),
+                                ),
+                            ]
+                        ),
+                    ),
+                    (
+                        "embed_block",
+                        wagtail.embeds.blocks.EmbedBlock(
+                            help_text="Insert an embed URL e.g https://www.youtube.com/embed/SGJFWirQ3ks",
+                            icon="fa-s15",
+                            template="blocks/embed_block.html",
+                        ),
+                    ),
+                ],
+                blank=True,
+                use_json_field=True,
+                verbose_name="Page body",
+            ),
         ),
         ),
     ]
     ]

+ 43 - 52
bakerydemo/blog/models.py

@@ -26,15 +26,14 @@ class BlogPeopleRelationship(Orderable, models.Model):
     We have created a two way relationship between BlogPage and People using
     We have created a two way relationship between BlogPage and People using
     the ParentalKey and ForeignKey
     the ParentalKey and ForeignKey
     """
     """
+
     page = ParentalKey(
     page = ParentalKey(
-        'BlogPage', related_name='blog_person_relationship', on_delete=models.CASCADE
+        "BlogPage", related_name="blog_person_relationship", on_delete=models.CASCADE
     )
     )
     people = models.ForeignKey(
     people = models.ForeignKey(
-        'base.People', related_name='person_blog_relationship', on_delete=models.CASCADE
+        "base.People", related_name="person_blog_relationship", on_delete=models.CASCADE
     )
     )
-    panels = [
-        FieldPanel('people')
-    ]
+    panels = [FieldPanel("people")]
 
 
 
 
 class BlogPageTag(TaggedItemBase):
 class BlogPageTag(TaggedItemBase):
@@ -43,7 +42,10 @@ class BlogPageTag(TaggedItemBase):
     the BlogPage object and tags. There's a longer guide on using it at
     the BlogPage object and tags. There's a longer guide on using it at
     https://docs.wagtail.org/en/stable/reference/pages/model_recipes.html#tagging
     https://docs.wagtail.org/en/stable/reference/pages/model_recipes.html#tagging
     """
     """
-    content_object = ParentalKey('BlogPage', related_name='tagged_items', on_delete=models.CASCADE)
+
+    content_object = ParentalKey(
+        "BlogPage", related_name="tagged_items", on_delete=models.CASCADE
+    )
 
 
 
 
 class BlogPage(Page):
 class BlogPage(Page):
@@ -54,40 +56,37 @@ class BlogPage(Page):
     ParentalKey's related_name in BlogPeopleRelationship. More docs:
     ParentalKey's related_name in BlogPeopleRelationship. More docs:
     https://docs.wagtail.org/en/stable/topics/pages.html#inline-models
     https://docs.wagtail.org/en/stable/topics/pages.html#inline-models
     """
     """
-    introduction = models.TextField(
-        help_text='Text to describe the page',
-        blank=True)
+
+    introduction = models.TextField(help_text="Text to describe the page", blank=True)
     image = models.ForeignKey(
     image = models.ForeignKey(
-        'wagtailimages.Image',
+        "wagtailimages.Image",
         null=True,
         null=True,
         blank=True,
         blank=True,
         on_delete=models.SET_NULL,
         on_delete=models.SET_NULL,
-        related_name='+',
-        help_text='Landscape mode only; horizontal width between 1000px and 3000px.'
+        related_name="+",
+        help_text="Landscape mode only; horizontal width between 1000px and 3000px.",
     )
     )
     body = StreamField(
     body = StreamField(
         BaseStreamBlock(), verbose_name="Page body", blank=True, use_json_field=True
         BaseStreamBlock(), verbose_name="Page body", blank=True, use_json_field=True
     )
     )
     subtitle = models.CharField(blank=True, max_length=255)
     subtitle = models.CharField(blank=True, max_length=255)
     tags = ClusterTaggableManager(through=BlogPageTag, blank=True)
     tags = ClusterTaggableManager(through=BlogPageTag, blank=True)
-    date_published = models.DateField(
-        "Date article published", blank=True, null=True
-    )
+    date_published = models.DateField("Date article published", blank=True, null=True)
 
 
     content_panels = Page.content_panels + [
     content_panels = Page.content_panels + [
-        FieldPanel('subtitle', classname="full"),
-        FieldPanel('introduction', classname="full"),
-        FieldPanel('image'),
-        FieldPanel('body'),
-        FieldPanel('date_published'),
+        FieldPanel("subtitle", classname="full"),
+        FieldPanel("introduction", classname="full"),
+        FieldPanel("image"),
+        FieldPanel("body"),
+        FieldPanel("date_published"),
         InlinePanel(
         InlinePanel(
-            'blog_person_relationship', label="Author(s)",
-            panels=None, min_num=1),
-        FieldPanel('tags'),
+            "blog_person_relationship", label="Author(s)", panels=None, min_num=1
+        ),
+        FieldPanel("tags"),
     ]
     ]
 
 
     search_fields = Page.search_fields + [
     search_fields = Page.search_fields + [
-        index.SearchField('body'),
+        index.SearchField("body"),
     ]
     ]
 
 
     def authors(self):
     def authors(self):
@@ -98,9 +97,7 @@ class BlogPage(Page):
         with a loop on the template. If we tried to access the blog_person_
         with a loop on the template. If we tried to access the blog_person_
         relationship directly we'd print `blog.BlogPeopleRelationship.None`
         relationship directly we'd print `blog.BlogPeopleRelationship.None`
         """
         """
-        authors = [
-            n.people for n in self.blog_person_relationship.all()
-        ]
+        authors = [n.people for n in self.blog_person_relationship.all()]
 
 
         return authors
         return authors
 
 
@@ -113,15 +110,13 @@ class BlogPage(Page):
         """
         """
         tags = self.tags.all()
         tags = self.tags.all()
         for tag in tags:
         for tag in tags:
-            tag.url = '/' + '/'.join(s.strip('/') for s in [
-                self.get_parent().url,
-                'tags',
-                tag.slug
-            ])
+            tag.url = "/" + "/".join(
+                s.strip("/") for s in [self.get_parent().url, "tags", tag.slug]
+            )
         return tags
         return tags
 
 
     # Specifies parent to BlogPage as being BlogIndexPages
     # Specifies parent to BlogPage as being BlogIndexPages
-    parent_page_types = ['BlogIndexPage']
+    parent_page_types = ["BlogIndexPage"]
 
 
     # Specifies what content types can exist as children of BlogPage.
     # Specifies what content types can exist as children of BlogPage.
     # Empty list means that no child content types are allowed.
     # Empty list means that no child content types are allowed.
@@ -137,25 +132,24 @@ class BlogIndexPage(RoutablePageMixin, Page):
     RoutablePageMixin is used to allow for a custom sub-URL for the tag views
     RoutablePageMixin is used to allow for a custom sub-URL for the tag views
     defined above.
     defined above.
     """
     """
-    introduction = models.TextField(
-        help_text='Text to describe the page',
-        blank=True)
+
+    introduction = models.TextField(help_text="Text to describe the page", blank=True)
     image = models.ForeignKey(
     image = models.ForeignKey(
-        'wagtailimages.Image',
+        "wagtailimages.Image",
         null=True,
         null=True,
         blank=True,
         blank=True,
         on_delete=models.SET_NULL,
         on_delete=models.SET_NULL,
-        related_name='+',
-        help_text='Landscape mode only; horizontal width between 1000px and 3000px.'
+        related_name="+",
+        help_text="Landscape mode only; horizontal width between 1000px and 3000px.",
     )
     )
 
 
     content_panels = Page.content_panels + [
     content_panels = Page.content_panels + [
-        FieldPanel('introduction', classname="full"),
-        FieldPanel('image'),
+        FieldPanel("introduction", classname="full"),
+        FieldPanel("image"),
     ]
     ]
 
 
     # Speficies that only BlogPage objects can live under this index page
     # Speficies that only BlogPage objects can live under this index page
-    subpage_types = ['BlogPage']
+    subpage_types = ["BlogPage"]
 
 
     # Defines a method to access the children of the page (e.g. BlogPage
     # Defines a method to access the children of the page (e.g. BlogPage
     # objects). On the demo site we use this on the HomePage
     # objects). On the demo site we use this on the HomePage
@@ -167,17 +161,17 @@ class BlogIndexPage(RoutablePageMixin, Page):
     # https://docs.wagtail.org/en/stable/getting_started/tutorial.html#overriding-context
     # https://docs.wagtail.org/en/stable/getting_started/tutorial.html#overriding-context
     def get_context(self, request):
     def get_context(self, request):
         context = super(BlogIndexPage, self).get_context(request)
         context = super(BlogIndexPage, self).get_context(request)
-        context['posts'] = BlogPage.objects.descendant_of(
-            self).live().order_by(
-            '-date_published')
+        context["posts"] = (
+            BlogPage.objects.descendant_of(self).live().order_by("-date_published")
+        )
         return context
         return context
 
 
     # This defines a Custom view that utilizes Tags. This view will return all
     # This defines a Custom view that utilizes Tags. This view will return all
     # related BlogPages for a given Tag or redirect back to the BlogIndexPage.
     # related BlogPages for a given Tag or redirect back to the BlogIndexPage.
     # More information on RoutablePages is at
     # More information on RoutablePages is at
     # https://docs.wagtail.org/en/stable/reference/contrib/routablepage.html
     # https://docs.wagtail.org/en/stable/reference/contrib/routablepage.html
-    @route(r'^tags/$', name='tag_archive')
-    @route(r'^tags/([\w-]+)/$', name='tag_archive')
+    @route(r"^tags/$", name="tag_archive")
+    @route(r"^tags/([\w-]+)/$", name="tag_archive")
     def tag_archive(self, request, tag=None):
     def tag_archive(self, request, tag=None):
 
 
         try:
         try:
@@ -189,11 +183,8 @@ class BlogIndexPage(RoutablePageMixin, Page):
             return redirect(self.url)
             return redirect(self.url)
 
 
         posts = self.get_posts(tag=tag)
         posts = self.get_posts(tag=tag)
-        context = {
-            'tag': tag,
-            'posts': posts
-        }
-        return render(request, 'blog/blog_index_page.html', context)
+        context = {"tag": tag, "posts": posts}
+        return render(request, "blog/blog_index_page.html", context)
 
 
     def serve_preview(self, request, mode_name):
     def serve_preview(self, request, mode_name):
         # Needed for previews to work
         # Needed for previews to work

+ 291 - 39
bakerydemo/breads/migrations/0001_initial.py

@@ -16,84 +16,336 @@ class Migration(migrations.Migration):
     initial = True
     initial = True
 
 
     dependencies = [
     dependencies = [
-        ('wagtailcore', '0032_add_bulk_delete_page_permission'),
-        ('wagtailimages', '0018_remove_rendition_filter'),
+        ("wagtailcore", "0032_add_bulk_delete_page_permission"),
+        ("wagtailimages", "0018_remove_rendition_filter"),
     ]
     ]
 
 
     operations = [
     operations = [
         migrations.CreateModel(
         migrations.CreateModel(
-            name='BreadIngredient',
+            name="BreadIngredient",
             fields=[
             fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('name', models.CharField(max_length=255)),
+                (
+                    "id",
+                    models.AutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                ("name", models.CharField(max_length=255)),
             ],
             ],
             options={
             options={
-                'verbose_name_plural': 'Bread ingredients',
+                "verbose_name_plural": "Bread ingredients",
             },
             },
         ),
         ),
         migrations.CreateModel(
         migrations.CreateModel(
-            name='BreadPage',
+            name="BreadPage",
             fields=[
             fields=[
-                ('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.Page')),
-                ('introduction', models.TextField(blank=True, help_text='Text to describe the page')),
-                ('body', wagtail.fields.StreamField((('heading_block', wagtail.blocks.StructBlock((('heading_text', wagtail.blocks.CharBlock(classname='title', required=True)), ('size', wagtail.blocks.ChoiceBlock(blank=True, choices=[('', 'Select a header size'), ('h2', 'H2'), ('h3', 'H3'), ('h4', 'H4')], required=False))))), ('paragraph_block', wagtail.blocks.RichTextBlock(icon='fa-paragraph', template='blocks/paragraph_block.html')), ('image_block', wagtail.blocks.StructBlock((('image', wagtail.images.blocks.ImageChooserBlock(required=True)), ('caption', wagtail.blocks.CharBlock(required=False)), ('attribution', wagtail.blocks.CharBlock(required=False))))), ('block_quote', wagtail.blocks.StructBlock((('text', wagtail.blocks.TextBlock()), ('attribute_name', wagtail.blocks.CharBlock(blank=True, label='e.g. Guy Picciotto', required=False))))), ('embed_block', wagtail.embeds.blocks.EmbedBlock(help_text='Insert an embed URL e.g https://www.youtube.com/embed/SGJFWirQ3ks', icon='fa-s15', template='blocks/embed_block.html'))), blank=True, verbose_name='Page body')),
+                (
+                    "page_ptr",
+                    models.OneToOneField(
+                        auto_created=True,
+                        on_delete=django.db.models.deletion.CASCADE,
+                        parent_link=True,
+                        primary_key=True,
+                        serialize=False,
+                        to="wagtailcore.Page",
+                    ),
+                ),
+                (
+                    "introduction",
+                    models.TextField(blank=True, help_text="Text to describe the page"),
+                ),
+                (
+                    "body",
+                    wagtail.fields.StreamField(
+                        (
+                            (
+                                "heading_block",
+                                wagtail.blocks.StructBlock(
+                                    (
+                                        (
+                                            "heading_text",
+                                            wagtail.blocks.CharBlock(
+                                                classname="title", required=True
+                                            ),
+                                        ),
+                                        (
+                                            "size",
+                                            wagtail.blocks.ChoiceBlock(
+                                                blank=True,
+                                                choices=[
+                                                    ("", "Select a header size"),
+                                                    ("h2", "H2"),
+                                                    ("h3", "H3"),
+                                                    ("h4", "H4"),
+                                                ],
+                                                required=False,
+                                            ),
+                                        ),
+                                    )
+                                ),
+                            ),
+                            (
+                                "paragraph_block",
+                                wagtail.blocks.RichTextBlock(
+                                    icon="fa-paragraph",
+                                    template="blocks/paragraph_block.html",
+                                ),
+                            ),
+                            (
+                                "image_block",
+                                wagtail.blocks.StructBlock(
+                                    (
+                                        (
+                                            "image",
+                                            wagtail.images.blocks.ImageChooserBlock(
+                                                required=True
+                                            ),
+                                        ),
+                                        (
+                                            "caption",
+                                            wagtail.blocks.CharBlock(required=False),
+                                        ),
+                                        (
+                                            "attribution",
+                                            wagtail.blocks.CharBlock(required=False),
+                                        ),
+                                    )
+                                ),
+                            ),
+                            (
+                                "block_quote",
+                                wagtail.blocks.StructBlock(
+                                    (
+                                        ("text", wagtail.blocks.TextBlock()),
+                                        (
+                                            "attribute_name",
+                                            wagtail.blocks.CharBlock(
+                                                blank=True,
+                                                label="e.g. Guy Picciotto",
+                                                required=False,
+                                            ),
+                                        ),
+                                    )
+                                ),
+                            ),
+                            (
+                                "embed_block",
+                                wagtail.embeds.blocks.EmbedBlock(
+                                    help_text="Insert an embed URL e.g https://www.youtube.com/embed/SGJFWirQ3ks",
+                                    icon="fa-s15",
+                                    template="blocks/embed_block.html",
+                                ),
+                            ),
+                        ),
+                        blank=True,
+                        verbose_name="Page body",
+                    ),
+                ),
             ],
             ],
             options={
             options={
-                'abstract': False,
+                "abstract": False,
             },
             },
-            bases=('wagtailcore.page', models.Model),
+            bases=("wagtailcore.page", models.Model),
         ),
         ),
         migrations.CreateModel(
         migrations.CreateModel(
-            name='BreadsIndexPage',
+            name="BreadsIndexPage",
             fields=[
             fields=[
-                ('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.Page')),
-                ('introduction', models.TextField(blank=True, help_text='Text to describe the page')),
-                ('body', wagtail.fields.StreamField((('heading_block', wagtail.blocks.StructBlock((('heading_text', wagtail.blocks.CharBlock(classname='title', required=True)), ('size', wagtail.blocks.ChoiceBlock(blank=True, choices=[('', 'Select a header size'), ('h2', 'H2'), ('h3', 'H3'), ('h4', 'H4')], required=False))))), ('paragraph_block', wagtail.blocks.RichTextBlock(icon='fa-paragraph', template='blocks/paragraph_block.html')), ('image_block', wagtail.blocks.StructBlock((('image', wagtail.images.blocks.ImageChooserBlock(required=True)), ('caption', wagtail.blocks.CharBlock(required=False)), ('attribution', wagtail.blocks.CharBlock(required=False))))), ('block_quote', wagtail.blocks.StructBlock((('text', wagtail.blocks.TextBlock()), ('attribute_name', wagtail.blocks.CharBlock(blank=True, label='e.g. Guy Picciotto', required=False))))), ('embed_block', wagtail.embeds.blocks.EmbedBlock(help_text='Insert an embed URL e.g https://www.youtube.com/embed/SGJFWirQ3ks', icon='fa-s15', template='blocks/embed_block.html'))), blank=True, verbose_name='Page body')),
-                ('image', models.ForeignKey(blank=True, help_text='Landscape mode only; horizontal width between 1000px and 3000px.', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailimages.Image')),
+                (
+                    "page_ptr",
+                    models.OneToOneField(
+                        auto_created=True,
+                        on_delete=django.db.models.deletion.CASCADE,
+                        parent_link=True,
+                        primary_key=True,
+                        serialize=False,
+                        to="wagtailcore.Page",
+                    ),
+                ),
+                (
+                    "introduction",
+                    models.TextField(blank=True, help_text="Text to describe the page"),
+                ),
+                (
+                    "body",
+                    wagtail.fields.StreamField(
+                        (
+                            (
+                                "heading_block",
+                                wagtail.blocks.StructBlock(
+                                    (
+                                        (
+                                            "heading_text",
+                                            wagtail.blocks.CharBlock(
+                                                classname="title", required=True
+                                            ),
+                                        ),
+                                        (
+                                            "size",
+                                            wagtail.blocks.ChoiceBlock(
+                                                blank=True,
+                                                choices=[
+                                                    ("", "Select a header size"),
+                                                    ("h2", "H2"),
+                                                    ("h3", "H3"),
+                                                    ("h4", "H4"),
+                                                ],
+                                                required=False,
+                                            ),
+                                        ),
+                                    )
+                                ),
+                            ),
+                            (
+                                "paragraph_block",
+                                wagtail.blocks.RichTextBlock(
+                                    icon="fa-paragraph",
+                                    template="blocks/paragraph_block.html",
+                                ),
+                            ),
+                            (
+                                "image_block",
+                                wagtail.blocks.StructBlock(
+                                    (
+                                        (
+                                            "image",
+                                            wagtail.images.blocks.ImageChooserBlock(
+                                                required=True
+                                            ),
+                                        ),
+                                        (
+                                            "caption",
+                                            wagtail.blocks.CharBlock(required=False),
+                                        ),
+                                        (
+                                            "attribution",
+                                            wagtail.blocks.CharBlock(required=False),
+                                        ),
+                                    )
+                                ),
+                            ),
+                            (
+                                "block_quote",
+                                wagtail.blocks.StructBlock(
+                                    (
+                                        ("text", wagtail.blocks.TextBlock()),
+                                        (
+                                            "attribute_name",
+                                            wagtail.blocks.CharBlock(
+                                                blank=True,
+                                                label="e.g. Guy Picciotto",
+                                                required=False,
+                                            ),
+                                        ),
+                                    )
+                                ),
+                            ),
+                            (
+                                "embed_block",
+                                wagtail.embeds.blocks.EmbedBlock(
+                                    help_text="Insert an embed URL e.g https://www.youtube.com/embed/SGJFWirQ3ks",
+                                    icon="fa-s15",
+                                    template="blocks/embed_block.html",
+                                ),
+                            ),
+                        ),
+                        blank=True,
+                        verbose_name="Page body",
+                    ),
+                ),
+                (
+                    "image",
+                    models.ForeignKey(
+                        blank=True,
+                        help_text="Landscape mode only; horizontal width between 1000px and 3000px.",
+                        null=True,
+                        on_delete=django.db.models.deletion.SET_NULL,
+                        related_name="+",
+                        to="wagtailimages.Image",
+                    ),
+                ),
             ],
             ],
             options={
             options={
-                'abstract': False,
+                "abstract": False,
             },
             },
-            bases=('wagtailcore.page', models.Model),
+            bases=("wagtailcore.page", models.Model),
         ),
         ),
         migrations.CreateModel(
         migrations.CreateModel(
-            name='BreadType',
+            name="BreadType",
             fields=[
             fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('title', models.CharField(max_length=255)),
+                (
+                    "id",
+                    models.AutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                ("title", models.CharField(max_length=255)),
             ],
             ],
             options={
             options={
-                'verbose_name_plural': 'Bread types',
+                "verbose_name_plural": "Bread types",
             },
             },
         ),
         ),
         migrations.CreateModel(
         migrations.CreateModel(
-            name='Country',
+            name="Country",
             fields=[
             fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('title', models.CharField(max_length=100)),
+                (
+                    "id",
+                    models.AutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                ("title", models.CharField(max_length=100)),
             ],
             ],
             options={
             options={
-                'verbose_name_plural': 'Countries of Origin',
+                "verbose_name_plural": "Countries of Origin",
             },
             },
         ),
         ),
         migrations.AddField(
         migrations.AddField(
-            model_name='breadpage',
-            name='bread_type',
-            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='breads.BreadType'),
+            model_name="breadpage",
+            name="bread_type",
+            field=models.ForeignKey(
+                blank=True,
+                null=True,
+                on_delete=django.db.models.deletion.SET_NULL,
+                related_name="+",
+                to="breads.BreadType",
+            ),
         ),
         ),
         migrations.AddField(
         migrations.AddField(
-            model_name='breadpage',
-            name='image',
-            field=models.ForeignKey(blank=True, help_text='Landscape mode only; horizontal width between 1000px and 3000px.', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailimages.Image'),
+            model_name="breadpage",
+            name="image",
+            field=models.ForeignKey(
+                blank=True,
+                help_text="Landscape mode only; horizontal width between 1000px and 3000px.",
+                null=True,
+                on_delete=django.db.models.deletion.SET_NULL,
+                related_name="+",
+                to="wagtailimages.Image",
+            ),
         ),
         ),
         migrations.AddField(
         migrations.AddField(
-            model_name='breadpage',
-            name='ingredients',
-            field=modelcluster.fields.ParentalManyToManyField(blank=True, to='breads.BreadIngredient'),
+            model_name="breadpage",
+            name="ingredients",
+            field=modelcluster.fields.ParentalManyToManyField(
+                blank=True, to="breads.BreadIngredient"
+            ),
         ),
         ),
         migrations.AddField(
         migrations.AddField(
-            model_name='breadpage',
-            name='origin',
-            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='breads.Country'),
+            model_name="breadpage",
+            name="origin",
+            field=models.ForeignKey(
+                blank=True,
+                null=True,
+                on_delete=django.db.models.deletion.SET_NULL,
+                to="breads.Country",
+            ),
         ),
         ),
     ]
     ]

+ 3 - 3
bakerydemo/breads/migrations/0002_remove_breadsindexpage_body.py

@@ -8,12 +8,12 @@ from django.db import migrations
 class Migration(migrations.Migration):
 class Migration(migrations.Migration):
 
 
     dependencies = [
     dependencies = [
-        ('breads', '0001_initial'),
+        ("breads", "0001_initial"),
     ]
     ]
 
 
     operations = [
     operations = [
         migrations.RemoveField(
         migrations.RemoveField(
-            model_name='breadsindexpage',
-            name='body',
+            model_name="breadsindexpage",
+            name="body",
         ),
         ),
     ]
     ]

+ 83 - 4
bakerydemo/breads/migrations/0003_auto_20170329_0055.py

@@ -12,13 +12,92 @@ import wagtail.images.blocks
 class Migration(migrations.Migration):
 class Migration(migrations.Migration):
 
 
     dependencies = [
     dependencies = [
-        ('breads', '0002_remove_breadsindexpage_body'),
+        ("breads", "0002_remove_breadsindexpage_body"),
     ]
     ]
 
 
     operations = [
     operations = [
         migrations.AlterField(
         migrations.AlterField(
-            model_name='breadpage',
-            name='body',
-            field=wagtail.fields.StreamField((('heading_block', wagtail.blocks.StructBlock((('heading_text', wagtail.blocks.CharBlock(classname='title', required=True)), ('size', wagtail.blocks.ChoiceBlock(blank=True, choices=[('', 'Select a header size'), ('h2', 'H2'), ('h3', 'H3'), ('h4', 'H4')], required=False))))), ('paragraph_block', wagtail.blocks.RichTextBlock(icon='fa-paragraph', template='blocks/paragraph_block.html')), ('image_block', wagtail.blocks.StructBlock((('image', wagtail.images.blocks.ImageChooserBlock(required=True)), ('caption', wagtail.blocks.CharBlock(required=False)), ('attribution', wagtail.blocks.CharBlock(required=False))))), ('block_quote', wagtail.blocks.StructBlock((('text', wagtail.blocks.TextBlock()), ('attribute_name', wagtail.blocks.CharBlock(blank=True, label='e.g. Mary Berry', required=False))))), ('embed_block', wagtail.embeds.blocks.EmbedBlock(help_text='Insert an embed URL e.g https://www.youtube.com/embed/SGJFWirQ3ks', icon='fa-s15', template='blocks/embed_block.html'))), blank=True, verbose_name='Page body'),
+            model_name="breadpage",
+            name="body",
+            field=wagtail.fields.StreamField(
+                (
+                    (
+                        "heading_block",
+                        wagtail.blocks.StructBlock(
+                            (
+                                (
+                                    "heading_text",
+                                    wagtail.blocks.CharBlock(
+                                        classname="title", required=True
+                                    ),
+                                ),
+                                (
+                                    "size",
+                                    wagtail.blocks.ChoiceBlock(
+                                        blank=True,
+                                        choices=[
+                                            ("", "Select a header size"),
+                                            ("h2", "H2"),
+                                            ("h3", "H3"),
+                                            ("h4", "H4"),
+                                        ],
+                                        required=False,
+                                    ),
+                                ),
+                            )
+                        ),
+                    ),
+                    (
+                        "paragraph_block",
+                        wagtail.blocks.RichTextBlock(
+                            icon="fa-paragraph", template="blocks/paragraph_block.html"
+                        ),
+                    ),
+                    (
+                        "image_block",
+                        wagtail.blocks.StructBlock(
+                            (
+                                (
+                                    "image",
+                                    wagtail.images.blocks.ImageChooserBlock(
+                                        required=True
+                                    ),
+                                ),
+                                ("caption", wagtail.blocks.CharBlock(required=False)),
+                                (
+                                    "attribution",
+                                    wagtail.blocks.CharBlock(required=False),
+                                ),
+                            )
+                        ),
+                    ),
+                    (
+                        "block_quote",
+                        wagtail.blocks.StructBlock(
+                            (
+                                ("text", wagtail.blocks.TextBlock()),
+                                (
+                                    "attribute_name",
+                                    wagtail.blocks.CharBlock(
+                                        blank=True,
+                                        label="e.g. Mary Berry",
+                                        required=False,
+                                    ),
+                                ),
+                            )
+                        ),
+                    ),
+                    (
+                        "embed_block",
+                        wagtail.embeds.blocks.EmbedBlock(
+                            help_text="Insert an embed URL e.g https://www.youtube.com/embed/SGJFWirQ3ks",
+                            icon="fa-s15",
+                            template="blocks/embed_block.html",
+                        ),
+                    ),
+                ),
+                blank=True,
+                verbose_name="Page body",
+            ),
         ),
         ),
     ]
     ]

+ 84 - 4
bakerydemo/breads/migrations/0004_use_json_field_for_body_streamfield.py

@@ -10,13 +10,93 @@ import wagtail.images.blocks
 class Migration(migrations.Migration):
 class Migration(migrations.Migration):
 
 
     dependencies = [
     dependencies = [
-        ('breads', '0003_auto_20170329_0055'),
+        ("breads", "0003_auto_20170329_0055"),
     ]
     ]
 
 
     operations = [
     operations = [
         migrations.AlterField(
         migrations.AlterField(
-            model_name='breadpage',
-            name='body',
-            field=wagtail.fields.StreamField([('heading_block', wagtail.blocks.StructBlock([('heading_text', wagtail.blocks.CharBlock(form_classname='title', required=True)), ('size', wagtail.blocks.ChoiceBlock(blank=True, choices=[('', 'Select a header size'), ('h2', 'H2'), ('h3', 'H3'), ('h4', 'H4')], required=False))])), ('paragraph_block', wagtail.blocks.RichTextBlock(icon='fa-paragraph', template='blocks/paragraph_block.html')), ('image_block', wagtail.blocks.StructBlock([('image', wagtail.images.blocks.ImageChooserBlock(required=True)), ('caption', wagtail.blocks.CharBlock(required=False)), ('attribution', wagtail.blocks.CharBlock(required=False))])), ('block_quote', wagtail.blocks.StructBlock([('text', wagtail.blocks.TextBlock()), ('attribute_name', wagtail.blocks.CharBlock(blank=True, label='e.g. Mary Berry', required=False))])), ('embed_block', wagtail.embeds.blocks.EmbedBlock(help_text='Insert an embed URL e.g https://www.youtube.com/embed/SGJFWirQ3ks', icon='fa-s15', template='blocks/embed_block.html'))], blank=True, use_json_field=True, verbose_name='Page body'),
+            model_name="breadpage",
+            name="body",
+            field=wagtail.fields.StreamField(
+                [
+                    (
+                        "heading_block",
+                        wagtail.blocks.StructBlock(
+                            [
+                                (
+                                    "heading_text",
+                                    wagtail.blocks.CharBlock(
+                                        form_classname="title", required=True
+                                    ),
+                                ),
+                                (
+                                    "size",
+                                    wagtail.blocks.ChoiceBlock(
+                                        blank=True,
+                                        choices=[
+                                            ("", "Select a header size"),
+                                            ("h2", "H2"),
+                                            ("h3", "H3"),
+                                            ("h4", "H4"),
+                                        ],
+                                        required=False,
+                                    ),
+                                ),
+                            ]
+                        ),
+                    ),
+                    (
+                        "paragraph_block",
+                        wagtail.blocks.RichTextBlock(
+                            icon="fa-paragraph", template="blocks/paragraph_block.html"
+                        ),
+                    ),
+                    (
+                        "image_block",
+                        wagtail.blocks.StructBlock(
+                            [
+                                (
+                                    "image",
+                                    wagtail.images.blocks.ImageChooserBlock(
+                                        required=True
+                                    ),
+                                ),
+                                ("caption", wagtail.blocks.CharBlock(required=False)),
+                                (
+                                    "attribution",
+                                    wagtail.blocks.CharBlock(required=False),
+                                ),
+                            ]
+                        ),
+                    ),
+                    (
+                        "block_quote",
+                        wagtail.blocks.StructBlock(
+                            [
+                                ("text", wagtail.blocks.TextBlock()),
+                                (
+                                    "attribute_name",
+                                    wagtail.blocks.CharBlock(
+                                        blank=True,
+                                        label="e.g. Mary Berry",
+                                        required=False,
+                                    ),
+                                ),
+                            ]
+                        ),
+                    ),
+                    (
+                        "embed_block",
+                        wagtail.embeds.blocks.EmbedBlock(
+                            help_text="Insert an embed URL e.g https://www.youtube.com/embed/SGJFWirQ3ks",
+                            icon="fa-s15",
+                            template="blocks/embed_block.html",
+                        ),
+                    ),
+                ],
+                blank=True,
+                use_json_field=True,
+                verbose_name="Page body",
+            ),
         ),
         ),
     ]
     ]

+ 34 - 38
bakerydemo/breads/models.py

@@ -4,9 +4,7 @@ from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
 
 
 from modelcluster.fields import ParentalManyToManyField
 from modelcluster.fields import ParentalManyToManyField
 
 
-from wagtail.admin.panels import (
-    FieldPanel, MultiFieldPanel
-)
+from wagtail.admin.panels import FieldPanel, MultiFieldPanel
 from wagtail.fields import StreamField
 from wagtail.fields import StreamField
 from wagtail.models import Page
 from wagtail.models import Page
 from wagtail.search import index
 from wagtail.search import index
@@ -45,17 +43,18 @@ class BreadIngredient(models.Model):
     model to display this. The Wagtail Docs give a slightly more detailed example
     model to display this. The Wagtail Docs give a slightly more detailed example
     https://docs.wagtail.org/en/stable/getting_started/tutorial.html#categories
     https://docs.wagtail.org/en/stable/getting_started/tutorial.html#categories
     """
     """
+
     name = models.CharField(max_length=255)
     name = models.CharField(max_length=255)
 
 
     panels = [
     panels = [
-        FieldPanel('name'),
+        FieldPanel("name"),
     ]
     ]
 
 
     def __str__(self):
     def __str__(self):
         return self.name
         return self.name
 
 
     class Meta:
     class Meta:
-        verbose_name_plural = 'Bread ingredients'
+        verbose_name_plural = "Bread ingredients"
 
 
 
 
 @register_snippet
 @register_snippet
@@ -72,7 +71,7 @@ class BreadType(models.Model):
     title = models.CharField(max_length=255)
     title = models.CharField(max_length=255)
 
 
     panels = [
     panels = [
-        FieldPanel('title'),
+        FieldPanel("title"),
     ]
     ]
 
 
     def __str__(self):
     def __str__(self):
@@ -86,16 +85,15 @@ class BreadPage(Page):
     """
     """
     Detail view for a specific bread
     Detail view for a specific bread
     """
     """
-    introduction = models.TextField(
-        help_text='Text to describe the page',
-        blank=True)
+
+    introduction = models.TextField(help_text="Text to describe the page", blank=True)
     image = models.ForeignKey(
     image = models.ForeignKey(
-        'wagtailimages.Image',
+        "wagtailimages.Image",
         null=True,
         null=True,
         blank=True,
         blank=True,
         on_delete=models.SET_NULL,
         on_delete=models.SET_NULL,
-        related_name='+',
-        help_text='Landscape mode only; horizontal width between 1000px and 3000px.'
+        related_name="+",
+        help_text="Landscape mode only; horizontal width between 1000px and 3000px.",
     )
     )
     body = StreamField(
     body = StreamField(
         BaseStreamBlock(), verbose_name="Page body", blank=True, use_json_field=True
         BaseStreamBlock(), verbose_name="Page body", blank=True, use_json_field=True
@@ -113,37 +111,37 @@ class BreadPage(Page):
     # relationship called `foopage_objects` that will throw a valueError on
     # relationship called `foopage_objects` that will throw a valueError on
     # collision.
     # collision.
     bread_type = models.ForeignKey(
     bread_type = models.ForeignKey(
-        'breads.BreadType',
+        "breads.BreadType",
         null=True,
         null=True,
         blank=True,
         blank=True,
         on_delete=models.SET_NULL,
         on_delete=models.SET_NULL,
-        related_name='+'
+        related_name="+",
     )
     )
-    ingredients = ParentalManyToManyField('BreadIngredient', blank=True)
+    ingredients = ParentalManyToManyField("BreadIngredient", blank=True)
 
 
     content_panels = Page.content_panels + [
     content_panels = Page.content_panels + [
-        FieldPanel('introduction', classname="full"),
-        FieldPanel('image'),
-        FieldPanel('body'),
-        FieldPanel('origin'),
-        FieldPanel('bread_type'),
+        FieldPanel("introduction", classname="full"),
+        FieldPanel("image"),
+        FieldPanel("body"),
+        FieldPanel("origin"),
+        FieldPanel("bread_type"),
         MultiFieldPanel(
         MultiFieldPanel(
             [
             [
                 FieldPanel(
                 FieldPanel(
-                    'ingredients',
+                    "ingredients",
                     widget=forms.CheckboxSelectMultiple,
                     widget=forms.CheckboxSelectMultiple,
                 ),
                 ),
             ],
             ],
             heading="Additional Metadata",
             heading="Additional Metadata",
-            classname="collapsible collapsed"
+            classname="collapsible collapsed",
         ),
         ),
     ]
     ]
 
 
     search_fields = Page.search_fields + [
     search_fields = Page.search_fields + [
-        index.SearchField('body'),
+        index.SearchField("body"),
     ]
     ]
 
 
-    parent_page_types = ['BreadsIndexPage']
+    parent_page_types = ["BreadsIndexPage"]
 
 
 
 
 class BreadsIndexPage(Page):
 class BreadsIndexPage(Page):
@@ -155,32 +153,30 @@ class BreadsIndexPage(Page):
     to be discrete functions to make it easier to follow
     to be discrete functions to make it easier to follow
     """
     """
 
 
-    introduction = models.TextField(
-        help_text='Text to describe the page',
-        blank=True)
+    introduction = models.TextField(help_text="Text to describe the page", blank=True)
     image = models.ForeignKey(
     image = models.ForeignKey(
-        'wagtailimages.Image',
+        "wagtailimages.Image",
         null=True,
         null=True,
         blank=True,
         blank=True,
         on_delete=models.SET_NULL,
         on_delete=models.SET_NULL,
-        related_name='+',
-        help_text='Landscape mode only; horizontal width between 1000px and '
-        '3000px.'
+        related_name="+",
+        help_text="Landscape mode only; horizontal width between 1000px and " "3000px.",
     )
     )
 
 
     content_panels = Page.content_panels + [
     content_panels = Page.content_panels + [
-        FieldPanel('introduction', classname="full"),
-        FieldPanel('image'),
+        FieldPanel("introduction", classname="full"),
+        FieldPanel("image"),
     ]
     ]
 
 
     # Can only have BreadPage children
     # Can only have BreadPage children
-    subpage_types = ['BreadPage']
+    subpage_types = ["BreadPage"]
 
 
     # Returns a queryset of BreadPage objects that are live, that are direct
     # Returns a queryset of BreadPage objects that are live, that are direct
     # descendants of this index page with most recent first
     # descendants of this index page with most recent first
     def get_breads(self):
     def get_breads(self):
-        return BreadPage.objects.live().descendant_of(
-            self).order_by('-first_published_at')
+        return (
+            BreadPage.objects.live().descendant_of(self).order_by("-first_published_at")
+        )
 
 
     # Allows child objects (e.g. BreadPage objects) to be accessible via the
     # Allows child objects (e.g. BreadPage objects) to be accessible via the
     # template. We use this on the HomePage to display child items of featured
     # template. We use this on the HomePage to display child items of featured
@@ -192,7 +188,7 @@ class BreadsIndexPage(Page):
     # standard Django app would, but the difference here being we have it as a
     # standard Django app would, but the difference here being we have it as a
     # method on the model rather than within a view function
     # method on the model rather than within a view function
     def paginate(self, request, *args):
     def paginate(self, request, *args):
-        page = request.GET.get('page')
+        page = request.GET.get("page")
         paginator = Paginator(self.get_breads(), 12)
         paginator = Paginator(self.get_breads(), 12)
         try:
         try:
             pages = paginator.page(page)
             pages = paginator.page(page)
@@ -210,6 +206,6 @@ class BreadsIndexPage(Page):
         # BreadPage objects (get_breads) are passed through pagination
         # BreadPage objects (get_breads) are passed through pagination
         breads = self.paginate(request, self.get_breads())
         breads = self.paginate(request, self.get_breads())
 
 
-        context['breads'] = breads
+        context["breads"] = breads
 
 
         return context
         return context

+ 7 - 8
bakerydemo/locations/choices.py

@@ -1,10 +1,9 @@
-
 DAY_CHOICES = (
 DAY_CHOICES = (
-    ('MON', 'Monday'),
-    ('TUES', 'Tuesday'),
-    ('WED', 'Wednesday'),
-    ('THUR', 'Thursday'),
-    ('FRI', 'Friday'),
-    ('SAT', 'Saturday'),
-    ('SUN', 'Sunday'),
+    ("MON", "Monday"),
+    ("TUES", "Tuesday"),
+    ("WED", "Wednesday"),
+    ("THUR", "Thursday"),
+    ("FRI", "Friday"),
+    ("SAT", "Saturday"),
+    ("SUN", "Sunday"),
 )
 )

+ 297 - 30
bakerydemo/locations/migrations/0001_initial.py

@@ -17,57 +17,324 @@ class Migration(migrations.Migration):
     initial = True
     initial = True
 
 
     dependencies = [
     dependencies = [
-        ('wagtailcore', '0032_add_bulk_delete_page_permission'),
-        ('wagtailimages', '0018_remove_rendition_filter'),
+        ("wagtailcore", "0032_add_bulk_delete_page_permission"),
+        ("wagtailimages", "0018_remove_rendition_filter"),
     ]
     ]
 
 
     operations = [
     operations = [
         migrations.CreateModel(
         migrations.CreateModel(
-            name='LocationOperatingHours',
+            name="LocationOperatingHours",
             fields=[
             fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('sort_order', models.IntegerField(blank=True, editable=False, null=True)),
-                ('day', models.CharField(choices=[('MON', 'Monday'), ('TUES', 'Tuesday'), ('WED', 'Wednesday'), ('THUR', 'Thursday'), ('FRI', 'Friday'), ('SAT', 'Saturday'), ('SUN', 'Sunday')], default='MON', max_length=4)),
-                ('opening_time', models.TimeField(blank=True, null=True)),
-                ('closing_time', models.TimeField(blank=True, null=True)),
-                ('closed', models.BooleanField(help_text='Tick if location is closed on this day', verbose_name='Closed?')),
+                (
+                    "id",
+                    models.AutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                (
+                    "sort_order",
+                    models.IntegerField(blank=True, editable=False, null=True),
+                ),
+                (
+                    "day",
+                    models.CharField(
+                        choices=[
+                            ("MON", "Monday"),
+                            ("TUES", "Tuesday"),
+                            ("WED", "Wednesday"),
+                            ("THUR", "Thursday"),
+                            ("FRI", "Friday"),
+                            ("SAT", "Saturday"),
+                            ("SUN", "Sunday"),
+                        ],
+                        default="MON",
+                        max_length=4,
+                    ),
+                ),
+                ("opening_time", models.TimeField(blank=True, null=True)),
+                ("closing_time", models.TimeField(blank=True, null=True)),
+                (
+                    "closed",
+                    models.BooleanField(
+                        help_text="Tick if location is closed on this day",
+                        verbose_name="Closed?",
+                    ),
+                ),
             ],
             ],
             options={
             options={
-                'ordering': ['sort_order'],
-                'abstract': False,
+                "ordering": ["sort_order"],
+                "abstract": False,
             },
             },
         ),
         ),
         migrations.CreateModel(
         migrations.CreateModel(
-            name='LocationPage',
+            name="LocationPage",
             fields=[
             fields=[
-                ('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.Page')),
-                ('introduction', models.TextField(blank=True, help_text='Text to describe the page')),
-                ('body', wagtail.fields.StreamField((('heading_block', wagtail.blocks.StructBlock((('heading_text', wagtail.blocks.CharBlock(classname='title', required=True)), ('size', wagtail.blocks.ChoiceBlock(blank=True, choices=[('', 'Select a header size'), ('h2', 'H2'), ('h3', 'H3'), ('h4', 'H4')], required=False))))), ('paragraph_block', wagtail.blocks.RichTextBlock(icon='fa-paragraph', template='blocks/paragraph_block.html')), ('image_block', wagtail.blocks.StructBlock((('image', wagtail.images.blocks.ImageChooserBlock(required=True)), ('caption', wagtail.blocks.CharBlock(required=False)), ('attribution', wagtail.blocks.CharBlock(required=False))))), ('block_quote', wagtail.blocks.StructBlock((('text', wagtail.blocks.TextBlock()), ('attribute_name', wagtail.blocks.CharBlock(blank=True, label='e.g. Guy Picciotto', required=False))))), ('embed_block', wagtail.embeds.blocks.EmbedBlock(help_text='Insert an embed URL e.g https://www.youtube.com/embed/SGJFWirQ3ks', icon='fa-s15', template='blocks/embed_block.html'))), blank=True, verbose_name='Page body')),
-                ('address', models.TextField()),
-                ('lat_long', models.CharField(help_text="Comma separated lat/long. (Ex. 64.144367, -21.939182)                    Right click Google Maps and select 'What's Here'", max_length=36, validators=[django.core.validators.RegexValidator(code='invalid_lat_long', message='Lat Long must be a comma-separated numeric lat and long', regex='^(\\-?\\d+(\\.\\d+)?),\\s*(\\-?\\d+(\\.\\d+)?)$')])),
-                ('image', models.ForeignKey(blank=True, help_text='Landscape mode only; horizontal width between 1000px and 3000px.', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailimages.Image')),
+                (
+                    "page_ptr",
+                    models.OneToOneField(
+                        auto_created=True,
+                        on_delete=django.db.models.deletion.CASCADE,
+                        parent_link=True,
+                        primary_key=True,
+                        serialize=False,
+                        to="wagtailcore.Page",
+                    ),
+                ),
+                (
+                    "introduction",
+                    models.TextField(blank=True, help_text="Text to describe the page"),
+                ),
+                (
+                    "body",
+                    wagtail.fields.StreamField(
+                        (
+                            (
+                                "heading_block",
+                                wagtail.blocks.StructBlock(
+                                    (
+                                        (
+                                            "heading_text",
+                                            wagtail.blocks.CharBlock(
+                                                classname="title", required=True
+                                            ),
+                                        ),
+                                        (
+                                            "size",
+                                            wagtail.blocks.ChoiceBlock(
+                                                blank=True,
+                                                choices=[
+                                                    ("", "Select a header size"),
+                                                    ("h2", "H2"),
+                                                    ("h3", "H3"),
+                                                    ("h4", "H4"),
+                                                ],
+                                                required=False,
+                                            ),
+                                        ),
+                                    )
+                                ),
+                            ),
+                            (
+                                "paragraph_block",
+                                wagtail.blocks.RichTextBlock(
+                                    icon="fa-paragraph",
+                                    template="blocks/paragraph_block.html",
+                                ),
+                            ),
+                            (
+                                "image_block",
+                                wagtail.blocks.StructBlock(
+                                    (
+                                        (
+                                            "image",
+                                            wagtail.images.blocks.ImageChooserBlock(
+                                                required=True
+                                            ),
+                                        ),
+                                        (
+                                            "caption",
+                                            wagtail.blocks.CharBlock(required=False),
+                                        ),
+                                        (
+                                            "attribution",
+                                            wagtail.blocks.CharBlock(required=False),
+                                        ),
+                                    )
+                                ),
+                            ),
+                            (
+                                "block_quote",
+                                wagtail.blocks.StructBlock(
+                                    (
+                                        ("text", wagtail.blocks.TextBlock()),
+                                        (
+                                            "attribute_name",
+                                            wagtail.blocks.CharBlock(
+                                                blank=True,
+                                                label="e.g. Guy Picciotto",
+                                                required=False,
+                                            ),
+                                        ),
+                                    )
+                                ),
+                            ),
+                            (
+                                "embed_block",
+                                wagtail.embeds.blocks.EmbedBlock(
+                                    help_text="Insert an embed URL e.g https://www.youtube.com/embed/SGJFWirQ3ks",
+                                    icon="fa-s15",
+                                    template="blocks/embed_block.html",
+                                ),
+                            ),
+                        ),
+                        blank=True,
+                        verbose_name="Page body",
+                    ),
+                ),
+                ("address", models.TextField()),
+                (
+                    "lat_long",
+                    models.CharField(
+                        help_text="Comma separated lat/long. (Ex. 64.144367, -21.939182)                    Right click Google Maps and select 'What's Here'",
+                        max_length=36,
+                        validators=[
+                            django.core.validators.RegexValidator(
+                                code="invalid_lat_long",
+                                message="Lat Long must be a comma-separated numeric lat and long",
+                                regex="^(\\-?\\d+(\\.\\d+)?),\\s*(\\-?\\d+(\\.\\d+)?)$",
+                            )
+                        ],
+                    ),
+                ),
+                (
+                    "image",
+                    models.ForeignKey(
+                        blank=True,
+                        help_text="Landscape mode only; horizontal width between 1000px and 3000px.",
+                        null=True,
+                        on_delete=django.db.models.deletion.SET_NULL,
+                        related_name="+",
+                        to="wagtailimages.Image",
+                    ),
+                ),
             ],
             ],
             options={
             options={
-                'abstract': False,
+                "abstract": False,
             },
             },
-            bases=('wagtailcore.page', models.Model),
+            bases=("wagtailcore.page", models.Model),
         ),
         ),
         migrations.CreateModel(
         migrations.CreateModel(
-            name='LocationsIndexPage',
+            name="LocationsIndexPage",
             fields=[
             fields=[
-                ('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.Page')),
-                ('introduction', models.TextField(blank=True, help_text='Text to describe the page')),
-                ('body', wagtail.fields.StreamField((('heading_block', wagtail.blocks.StructBlock((('heading_text', wagtail.blocks.CharBlock(classname='title', required=True)), ('size', wagtail.blocks.ChoiceBlock(blank=True, choices=[('', 'Select a header size'), ('h2', 'H2'), ('h3', 'H3'), ('h4', 'H4')], required=False))))), ('paragraph_block', wagtail.blocks.RichTextBlock(icon='fa-paragraph', template='blocks/paragraph_block.html')), ('image_block', wagtail.blocks.StructBlock((('image', wagtail.images.blocks.ImageChooserBlock(required=True)), ('caption', wagtail.blocks.CharBlock(required=False)), ('attribution', wagtail.blocks.CharBlock(required=False))))), ('block_quote', wagtail.blocks.StructBlock((('text', wagtail.blocks.TextBlock()), ('attribute_name', wagtail.blocks.CharBlock(blank=True, label='e.g. Guy Picciotto', required=False))))), ('embed_block', wagtail.embeds.blocks.EmbedBlock(help_text='Insert an embed URL e.g https://www.youtube.com/embed/SGJFWirQ3ks', icon='fa-s15', template='blocks/embed_block.html'))), blank=True, verbose_name='Page body')),
-                ('image', models.ForeignKey(blank=True, help_text='Landscape mode only; horizontal width between 1000px and 3000px.', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailimages.Image')),
+                (
+                    "page_ptr",
+                    models.OneToOneField(
+                        auto_created=True,
+                        on_delete=django.db.models.deletion.CASCADE,
+                        parent_link=True,
+                        primary_key=True,
+                        serialize=False,
+                        to="wagtailcore.Page",
+                    ),
+                ),
+                (
+                    "introduction",
+                    models.TextField(blank=True, help_text="Text to describe the page"),
+                ),
+                (
+                    "body",
+                    wagtail.fields.StreamField(
+                        (
+                            (
+                                "heading_block",
+                                wagtail.blocks.StructBlock(
+                                    (
+                                        (
+                                            "heading_text",
+                                            wagtail.blocks.CharBlock(
+                                                classname="title", required=True
+                                            ),
+                                        ),
+                                        (
+                                            "size",
+                                            wagtail.blocks.ChoiceBlock(
+                                                blank=True,
+                                                choices=[
+                                                    ("", "Select a header size"),
+                                                    ("h2", "H2"),
+                                                    ("h3", "H3"),
+                                                    ("h4", "H4"),
+                                                ],
+                                                required=False,
+                                            ),
+                                        ),
+                                    )
+                                ),
+                            ),
+                            (
+                                "paragraph_block",
+                                wagtail.blocks.RichTextBlock(
+                                    icon="fa-paragraph",
+                                    template="blocks/paragraph_block.html",
+                                ),
+                            ),
+                            (
+                                "image_block",
+                                wagtail.blocks.StructBlock(
+                                    (
+                                        (
+                                            "image",
+                                            wagtail.images.blocks.ImageChooserBlock(
+                                                required=True
+                                            ),
+                                        ),
+                                        (
+                                            "caption",
+                                            wagtail.blocks.CharBlock(required=False),
+                                        ),
+                                        (
+                                            "attribution",
+                                            wagtail.blocks.CharBlock(required=False),
+                                        ),
+                                    )
+                                ),
+                            ),
+                            (
+                                "block_quote",
+                                wagtail.blocks.StructBlock(
+                                    (
+                                        ("text", wagtail.blocks.TextBlock()),
+                                        (
+                                            "attribute_name",
+                                            wagtail.blocks.CharBlock(
+                                                blank=True,
+                                                label="e.g. Guy Picciotto",
+                                                required=False,
+                                            ),
+                                        ),
+                                    )
+                                ),
+                            ),
+                            (
+                                "embed_block",
+                                wagtail.embeds.blocks.EmbedBlock(
+                                    help_text="Insert an embed URL e.g https://www.youtube.com/embed/SGJFWirQ3ks",
+                                    icon="fa-s15",
+                                    template="blocks/embed_block.html",
+                                ),
+                            ),
+                        ),
+                        blank=True,
+                        verbose_name="Page body",
+                    ),
+                ),
+                (
+                    "image",
+                    models.ForeignKey(
+                        blank=True,
+                        help_text="Landscape mode only; horizontal width between 1000px and 3000px.",
+                        null=True,
+                        on_delete=django.db.models.deletion.SET_NULL,
+                        related_name="+",
+                        to="wagtailimages.Image",
+                    ),
+                ),
             ],
             ],
             options={
             options={
-                'abstract': False,
+                "abstract": False,
             },
             },
-            bases=('wagtailcore.page', models.Model),
+            bases=("wagtailcore.page", models.Model),
         ),
         ),
         migrations.AddField(
         migrations.AddField(
-            model_name='locationoperatinghours',
-            name='location',
-            field=modelcluster.fields.ParentalKey(on_delete=django.db.models.deletion.CASCADE, related_name='hours_of_operation', to='locations.LocationPage'),
+            model_name="locationoperatinghours",
+            name="location",
+            field=modelcluster.fields.ParentalKey(
+                on_delete=django.db.models.deletion.CASCADE,
+                related_name="hours_of_operation",
+                to="locations.LocationPage",
+            ),
         ),
         ),
     ]
     ]

+ 3 - 3
bakerydemo/locations/migrations/0002_remove_locationsindexpage_body.py

@@ -8,12 +8,12 @@ from django.db import migrations
 class Migration(migrations.Migration):
 class Migration(migrations.Migration):
 
 
     dependencies = [
     dependencies = [
-        ('locations', '0001_initial'),
+        ("locations", "0001_initial"),
     ]
     ]
 
 
     operations = [
     operations = [
         migrations.RemoveField(
         migrations.RemoveField(
-            model_name='locationsindexpage',
-            name='body',
+            model_name="locationsindexpage",
+            name="body",
         ),
         ),
     ]
     ]

+ 83 - 4
bakerydemo/locations/migrations/0003_auto_20170329_0055.py

@@ -12,13 +12,92 @@ import wagtail.images.blocks
 class Migration(migrations.Migration):
 class Migration(migrations.Migration):
 
 
     dependencies = [
     dependencies = [
-        ('locations', '0002_remove_locationsindexpage_body'),
+        ("locations", "0002_remove_locationsindexpage_body"),
     ]
     ]
 
 
     operations = [
     operations = [
         migrations.AlterField(
         migrations.AlterField(
-            model_name='locationpage',
-            name='body',
-            field=wagtail.fields.StreamField((('heading_block', wagtail.blocks.StructBlock((('heading_text', wagtail.blocks.CharBlock(classname='title', required=True)), ('size', wagtail.blocks.ChoiceBlock(blank=True, choices=[('', 'Select a header size'), ('h2', 'H2'), ('h3', 'H3'), ('h4', 'H4')], required=False))))), ('paragraph_block', wagtail.blocks.RichTextBlock(icon='fa-paragraph', template='blocks/paragraph_block.html')), ('image_block', wagtail.blocks.StructBlock((('image', wagtail.images.blocks.ImageChooserBlock(required=True)), ('caption', wagtail.blocks.CharBlock(required=False)), ('attribution', wagtail.blocks.CharBlock(required=False))))), ('block_quote', wagtail.blocks.StructBlock((('text', wagtail.blocks.TextBlock()), ('attribute_name', wagtail.blocks.CharBlock(blank=True, label='e.g. Mary Berry', required=False))))), ('embed_block', wagtail.embeds.blocks.EmbedBlock(help_text='Insert an embed URL e.g https://www.youtube.com/embed/SGJFWirQ3ks', icon='fa-s15', template='blocks/embed_block.html'))), blank=True, verbose_name='Page body'),
+            model_name="locationpage",
+            name="body",
+            field=wagtail.fields.StreamField(
+                (
+                    (
+                        "heading_block",
+                        wagtail.blocks.StructBlock(
+                            (
+                                (
+                                    "heading_text",
+                                    wagtail.blocks.CharBlock(
+                                        classname="title", required=True
+                                    ),
+                                ),
+                                (
+                                    "size",
+                                    wagtail.blocks.ChoiceBlock(
+                                        blank=True,
+                                        choices=[
+                                            ("", "Select a header size"),
+                                            ("h2", "H2"),
+                                            ("h3", "H3"),
+                                            ("h4", "H4"),
+                                        ],
+                                        required=False,
+                                    ),
+                                ),
+                            )
+                        ),
+                    ),
+                    (
+                        "paragraph_block",
+                        wagtail.blocks.RichTextBlock(
+                            icon="fa-paragraph", template="blocks/paragraph_block.html"
+                        ),
+                    ),
+                    (
+                        "image_block",
+                        wagtail.blocks.StructBlock(
+                            (
+                                (
+                                    "image",
+                                    wagtail.images.blocks.ImageChooserBlock(
+                                        required=True
+                                    ),
+                                ),
+                                ("caption", wagtail.blocks.CharBlock(required=False)),
+                                (
+                                    "attribution",
+                                    wagtail.blocks.CharBlock(required=False),
+                                ),
+                            )
+                        ),
+                    ),
+                    (
+                        "block_quote",
+                        wagtail.blocks.StructBlock(
+                            (
+                                ("text", wagtail.blocks.TextBlock()),
+                                (
+                                    "attribute_name",
+                                    wagtail.blocks.CharBlock(
+                                        blank=True,
+                                        label="e.g. Mary Berry",
+                                        required=False,
+                                    ),
+                                ),
+                            )
+                        ),
+                    ),
+                    (
+                        "embed_block",
+                        wagtail.embeds.blocks.EmbedBlock(
+                            help_text="Insert an embed URL e.g https://www.youtube.com/embed/SGJFWirQ3ks",
+                            icon="fa-s15",
+                            template="blocks/embed_block.html",
+                        ),
+                    ),
+                ),
+                blank=True,
+                verbose_name="Page body",
+            ),
         ),
         ),
     ]
     ]

+ 8 - 4
bakerydemo/locations/migrations/0004_auto_20190912_1149.py

@@ -6,13 +6,17 @@ from django.db import migrations, models
 class Migration(migrations.Migration):
 class Migration(migrations.Migration):
 
 
     dependencies = [
     dependencies = [
-        ('locations', '0003_auto_20170329_0055'),
+        ("locations", "0003_auto_20170329_0055"),
     ]
     ]
 
 
     operations = [
     operations = [
         migrations.AlterField(
         migrations.AlterField(
-            model_name='locationoperatinghours',
-            name='closed',
-            field=models.BooleanField(blank=True, help_text='Tick if location is closed on this day', verbose_name='Closed?'),
+            model_name="locationoperatinghours",
+            name="closed",
+            field=models.BooleanField(
+                blank=True,
+                help_text="Tick if location is closed on this day",
+                verbose_name="Closed?",
+            ),
         ),
         ),
     ]
     ]

+ 84 - 4
bakerydemo/locations/migrations/0005_use_json_field_for_body_streamfield.py

@@ -10,13 +10,93 @@ import wagtail.images.blocks
 class Migration(migrations.Migration):
 class Migration(migrations.Migration):
 
 
     dependencies = [
     dependencies = [
-        ('locations', '0004_auto_20190912_1149'),
+        ("locations", "0004_auto_20190912_1149"),
     ]
     ]
 
 
     operations = [
     operations = [
         migrations.AlterField(
         migrations.AlterField(
-            model_name='locationpage',
-            name='body',
-            field=wagtail.fields.StreamField([('heading_block', wagtail.blocks.StructBlock([('heading_text', wagtail.blocks.CharBlock(form_classname='title', required=True)), ('size', wagtail.blocks.ChoiceBlock(blank=True, choices=[('', 'Select a header size'), ('h2', 'H2'), ('h3', 'H3'), ('h4', 'H4')], required=False))])), ('paragraph_block', wagtail.blocks.RichTextBlock(icon='fa-paragraph', template='blocks/paragraph_block.html')), ('image_block', wagtail.blocks.StructBlock([('image', wagtail.images.blocks.ImageChooserBlock(required=True)), ('caption', wagtail.blocks.CharBlock(required=False)), ('attribution', wagtail.blocks.CharBlock(required=False))])), ('block_quote', wagtail.blocks.StructBlock([('text', wagtail.blocks.TextBlock()), ('attribute_name', wagtail.blocks.CharBlock(blank=True, label='e.g. Mary Berry', required=False))])), ('embed_block', wagtail.embeds.blocks.EmbedBlock(help_text='Insert an embed URL e.g https://www.youtube.com/embed/SGJFWirQ3ks', icon='fa-s15', template='blocks/embed_block.html'))], blank=True, use_json_field=True, verbose_name='Page body'),
+            model_name="locationpage",
+            name="body",
+            field=wagtail.fields.StreamField(
+                [
+                    (
+                        "heading_block",
+                        wagtail.blocks.StructBlock(
+                            [
+                                (
+                                    "heading_text",
+                                    wagtail.blocks.CharBlock(
+                                        form_classname="title", required=True
+                                    ),
+                                ),
+                                (
+                                    "size",
+                                    wagtail.blocks.ChoiceBlock(
+                                        blank=True,
+                                        choices=[
+                                            ("", "Select a header size"),
+                                            ("h2", "H2"),
+                                            ("h3", "H3"),
+                                            ("h4", "H4"),
+                                        ],
+                                        required=False,
+                                    ),
+                                ),
+                            ]
+                        ),
+                    ),
+                    (
+                        "paragraph_block",
+                        wagtail.blocks.RichTextBlock(
+                            icon="fa-paragraph", template="blocks/paragraph_block.html"
+                        ),
+                    ),
+                    (
+                        "image_block",
+                        wagtail.blocks.StructBlock(
+                            [
+                                (
+                                    "image",
+                                    wagtail.images.blocks.ImageChooserBlock(
+                                        required=True
+                                    ),
+                                ),
+                                ("caption", wagtail.blocks.CharBlock(required=False)),
+                                (
+                                    "attribution",
+                                    wagtail.blocks.CharBlock(required=False),
+                                ),
+                            ]
+                        ),
+                    ),
+                    (
+                        "block_quote",
+                        wagtail.blocks.StructBlock(
+                            [
+                                ("text", wagtail.blocks.TextBlock()),
+                                (
+                                    "attribute_name",
+                                    wagtail.blocks.CharBlock(
+                                        blank=True,
+                                        label="e.g. Mary Berry",
+                                        required=False,
+                                    ),
+                                ),
+                            ]
+                        ),
+                    ),
+                    (
+                        "embed_block",
+                        wagtail.embeds.blocks.EmbedBlock(
+                            help_text="Insert an embed URL e.g https://www.youtube.com/embed/SGJFWirQ3ks",
+                            icon="fa-s15",
+                            template="blocks/embed_block.html",
+                        ),
+                    ),
+                ],
+                blank=True,
+                use_json_field=True,
+                verbose_name="Page body",
+            ),
         ),
         ),
     ]
     ]

+ 51 - 71
bakerydemo/locations/models.py

@@ -20,30 +20,18 @@ class OperatingHours(models.Model):
     A Django model to capture operating hours for a Location
     A Django model to capture operating hours for a Location
     """
     """
 
 
-    day = models.CharField(
-        max_length=4,
-        choices=DAY_CHOICES,
-        default='MON'
-    )
-    opening_time = models.TimeField(
-        blank=True,
-        null=True
-    )
-    closing_time = models.TimeField(
-        blank=True,
-        null=True
-    )
+    day = models.CharField(max_length=4, choices=DAY_CHOICES, default="MON")
+    opening_time = models.TimeField(blank=True, null=True)
+    closing_time = models.TimeField(blank=True, null=True)
     closed = models.BooleanField(
     closed = models.BooleanField(
-        "Closed?",
-        blank=True,
-        help_text='Tick if location is closed on this day'
+        "Closed?", blank=True, help_text="Tick if location is closed on this day"
     )
     )
 
 
     panels = [
     panels = [
-        FieldPanel('day'),
-        FieldPanel('opening_time'),
-        FieldPanel('closing_time'),
-        FieldPanel('closed'),
+        FieldPanel("day"),
+        FieldPanel("opening_time"),
+        FieldPanel("closing_time"),
+        FieldPanel("closed"),
     ]
     ]
 
 
     class Meta:
     class Meta:
@@ -51,19 +39,14 @@ class OperatingHours(models.Model):
 
 
     def __str__(self):
     def __str__(self):
         if self.opening_time:
         if self.opening_time:
-            opening = self.opening_time.strftime('%H:%M')
+            opening = self.opening_time.strftime("%H:%M")
         else:
         else:
-            opening = '--'
+            opening = "--"
         if self.closing_time:
         if self.closing_time:
-            closed = self.closing_time.strftime('%H:%M')
+            closed = self.closing_time.strftime("%H:%M")
         else:
         else:
-            closed = '--'
-        return '{}: {} - {} {}'.format(
-            self.day,
-            opening,
-            closed,
-            settings.TIME_ZONE
-        )
+            closed = "--"
+        return "{}: {} - {} {}".format(self.day, opening, closed, settings.TIME_ZONE)
 
 
 
 
 class LocationOperatingHours(Orderable, OperatingHours):
 class LocationOperatingHours(Orderable, OperatingHours):
@@ -75,10 +58,9 @@ class LocationOperatingHours(Orderable, OperatingHours):
     relate the two objects to one another. We use the ParentalKey's related_
     relate the two objects to one another. We use the ParentalKey's related_
     name to access it from the LocationPage admin
     name to access it from the LocationPage admin
     """
     """
+
     location = ParentalKey(
     location = ParentalKey(
-        'LocationPage',
-        related_name='hours_of_operation',
-        on_delete=models.CASCADE
+        "LocationPage", related_name="hours_of_operation", on_delete=models.CASCADE
     )
     )
 
 
 
 
@@ -86,20 +68,19 @@ class LocationsIndexPage(Page):
     """
     """
     A Page model that creates an index page (a listview)
     A Page model that creates an index page (a listview)
     """
     """
-    introduction = models.TextField(
-        help_text='Text to describe the page',
-        blank=True)
+
+    introduction = models.TextField(help_text="Text to describe the page", blank=True)
     image = models.ForeignKey(
     image = models.ForeignKey(
-        'wagtailimages.Image',
+        "wagtailimages.Image",
         null=True,
         null=True,
         blank=True,
         blank=True,
         on_delete=models.SET_NULL,
         on_delete=models.SET_NULL,
-        related_name='+',
-        help_text='Landscape mode only; horizontal width between 1000px and 3000px.'
+        related_name="+",
+        help_text="Landscape mode only; horizontal width between 1000px and 3000px.",
     )
     )
 
 
     # Only LocationPage objects can be added underneath this index page
     # Only LocationPage objects can be added underneath this index page
-    subpage_types = ['LocationPage']
+    subpage_types = ["LocationPage"]
 
 
     # Allows children of this indexpage to be accessible via the indexpage
     # Allows children of this indexpage to be accessible via the indexpage
     # object on templates. We use this on the homepage to show featured
     # object on templates. We use this on the homepage to show featured
@@ -112,14 +93,14 @@ class LocationsIndexPage(Page):
     # https://docs.wagtail.org/en/stable/getting_started/tutorial.html#overriding-context
     # https://docs.wagtail.org/en/stable/getting_started/tutorial.html#overriding-context
     def get_context(self, request):
     def get_context(self, request):
         context = super(LocationsIndexPage, self).get_context(request)
         context = super(LocationsIndexPage, self).get_context(request)
-        context['locations'] = LocationPage.objects.descendant_of(
-            self).live().order_by(
-            'title')
+        context["locations"] = (
+            LocationPage.objects.descendant_of(self).live().order_by("title")
+        )
         return context
         return context
 
 
     content_panels = Page.content_panels + [
     content_panels = Page.content_panels + [
-        FieldPanel('introduction', classname="full"),
-        FieldPanel('image'),
+        FieldPanel("introduction", classname="full"),
+        FieldPanel("image"),
     ]
     ]
 
 
 
 
@@ -127,16 +108,15 @@ class LocationPage(Page):
     """
     """
     Detail for a specific bakery location.
     Detail for a specific bakery location.
     """
     """
-    introduction = models.TextField(
-        help_text='Text to describe the page',
-        blank=True)
+
+    introduction = models.TextField(help_text="Text to describe the page", blank=True)
     image = models.ForeignKey(
     image = models.ForeignKey(
-        'wagtailimages.Image',
+        "wagtailimages.Image",
         null=True,
         null=True,
         blank=True,
         blank=True,
         on_delete=models.SET_NULL,
         on_delete=models.SET_NULL,
-        related_name='+',
-        help_text='Landscape mode only; horizontal width between 1000px and 3000px.'
+        related_name="+",
+        help_text="Landscape mode only; horizontal width between 1000px and 3000px.",
     )
     )
     body = StreamField(
     body = StreamField(
         BaseStreamBlock(), verbose_name="Page body", blank=True, use_json_field=True
         BaseStreamBlock(), verbose_name="Page body", blank=True, use_json_field=True
@@ -145,31 +125,31 @@ class LocationPage(Page):
     lat_long = models.CharField(
     lat_long = models.CharField(
         max_length=36,
         max_length=36,
         help_text="Comma separated lat/long. (Ex. 64.144367, -21.939182) \
         help_text="Comma separated lat/long. (Ex. 64.144367, -21.939182) \
-                   Right click Google Maps and select 'What\'s Here'",
+                   Right click Google Maps and select 'What's Here'",
         validators=[
         validators=[
             RegexValidator(
             RegexValidator(
-                regex=r'^(\-?\d+(\.\d+)?),\s*(\-?\d+(\.\d+)?)$',
-                message='Lat Long must be a comma-separated numeric lat and long',
-                code='invalid_lat_long'
+                regex=r"^(\-?\d+(\.\d+)?),\s*(\-?\d+(\.\d+)?)$",
+                message="Lat Long must be a comma-separated numeric lat and long",
+                code="invalid_lat_long",
             ),
             ),
-        ]
+        ],
     )
     )
 
 
     # Search index configuration
     # Search index configuration
     search_fields = Page.search_fields + [
     search_fields = Page.search_fields + [
-        index.SearchField('address'),
-        index.SearchField('body'),
+        index.SearchField("address"),
+        index.SearchField("body"),
     ]
     ]
 
 
     # Fields to show to the editor in the admin view
     # Fields to show to the editor in the admin view
     content_panels = [
     content_panels = [
-        FieldPanel('title', classname="full"),
-        FieldPanel('introduction', classname="full"),
-        FieldPanel('image'),
-        FieldPanel('body'),
-        FieldPanel('address', classname="full"),
-        FieldPanel('lat_long'),
-        InlinePanel('hours_of_operation', label="Hours of Operation"),
+        FieldPanel("title", classname="full"),
+        FieldPanel("introduction", classname="full"),
+        FieldPanel("image"),
+        FieldPanel("body"),
+        FieldPanel("address", classname="full"),
+        FieldPanel("lat_long"),
+        InlinePanel("hours_of_operation", label="Hours of Operation"),
     ]
     ]
 
 
     def __str__(self):
     def __str__(self):
@@ -184,12 +164,12 @@ class LocationPage(Page):
     def is_open(self):
     def is_open(self):
         now = datetime.now()
         now = datetime.now()
         current_time = now.time()
         current_time = now.time()
-        current_day = now.strftime('%a').upper()
+        current_day = now.strftime("%a").upper()
         try:
         try:
             self.operating_hours.get(
             self.operating_hours.get(
                 day=current_day,
                 day=current_day,
                 opening_time__lte=current_time,
                 opening_time__lte=current_time,
-                closing_time__gte=current_time
+                closing_time__gte=current_time,
             )
             )
             return True
             return True
         except LocationOperatingHours.DoesNotExist:
         except LocationOperatingHours.DoesNotExist:
@@ -199,10 +179,10 @@ class LocationPage(Page):
     # the latitude, longitude and map API key to render the map
     # the latitude, longitude and map API key to render the map
     def get_context(self, request):
     def get_context(self, request):
         context = super(LocationPage, self).get_context(request)
         context = super(LocationPage, self).get_context(request)
-        context['lat'] = self.lat_long.split(",")[0]
-        context['long'] = self.lat_long.split(",")[1]
-        context['google_map_api_key'] = settings.GOOGLE_MAP_API_KEY
+        context["lat"] = self.lat_long.split(",")[0]
+        context["long"] = self.lat_long.split(",")[1]
+        context["google_map_api_key"] = settings.GOOGLE_MAP_API_KEY
         return context
         return context
 
 
     # Can only be placed under a LocationsIndexPage object
     # Can only be placed under a LocationsIndexPage object
-    parent_page_types = ['LocationsIndexPage']
+    parent_page_types = ["LocationsIndexPage"]

+ 11 - 7
bakerydemo/search/views.py

@@ -12,9 +12,9 @@ from bakerydemo.locations.models import LocationPage
 
 
 def search(request):
 def search(request):
     # Search
     # Search
-    search_query = request.GET.get('q', None)
+    search_query = request.GET.get("q", None)
     if search_query:
     if search_query:
-        if 'elasticsearch' in settings.WAGTAILSEARCH_BACKENDS['default']['BACKEND']:
+        if "elasticsearch" in settings.WAGTAILSEARCH_BACKENDS["default"]["BACKEND"]:
             # In production, use ElasticSearch and a simplified search query, per
             # In production, use ElasticSearch and a simplified search query, per
             # https://docs.wagtail.org/en/stable/topics/search/backends.html
             # https://docs.wagtail.org/en/stable/topics/search/backends.html
             # like this:
             # like this:
@@ -44,7 +44,7 @@ def search(request):
         search_results = Page.objects.none()
         search_results = Page.objects.none()
 
 
     # Pagination
     # Pagination
-    page = request.GET.get('page', 1)
+    page = request.GET.get("page", 1)
     paginator = Paginator(search_results, 10)
     paginator = Paginator(search_results, 10)
     try:
     try:
         search_results = paginator.page(page)
         search_results = paginator.page(page)
@@ -53,7 +53,11 @@ def search(request):
     except EmptyPage:
     except EmptyPage:
         search_results = paginator.page(paginator.num_pages)
         search_results = paginator.page(paginator.num_pages)
 
 
-    return render(request, 'search/search_results.html', {
-        'search_query': search_query,
-        'search_results': search_results,
-    })
+    return render(
+        request,
+        "search/search_results.html",
+        {
+            "search_query": search_query,
+            "search_results": search_results,
+        },
+    )

+ 78 - 81
bakerydemo/settings/base.py

@@ -20,7 +20,7 @@ BASE_DIR = os.path.dirname(PROJECT_DIR)
 # See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/
 # See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/
 
 
 # SECURITY WARNING: keep the secret key used in production secret!
 # SECURITY WARNING: keep the secret key used in production secret!
-SECRET_KEY = 'c6u0-9c!7nilj_ysatsda0(f@e_2mws2f!6m0n^o*4#*q#kzp)'
+SECRET_KEY = "c6u0-9c!7nilj_ysatsda0(f@e_2mws2f!6m0n^o*4#*q#kzp)"
 
 
 # SECURITY WARNING: don't run with debug turned on in production!
 # SECURITY WARNING: don't run with debug turned on in production!
 DEBUG = True
 DEBUG = True
@@ -35,89 +35,86 @@ ALLOWED_HOSTS = []
 # Application definition
 # Application definition
 
 
 INSTALLED_APPS = [
 INSTALLED_APPS = [
-    'bakerydemo.base',
-    'bakerydemo.blog',
-    'bakerydemo.breads',
-    'bakerydemo.locations',
-    'bakerydemo.search',
-
-    'wagtail.contrib.search_promotions',
-    'wagtail.contrib.forms',
-    'wagtail.contrib.redirects',
-    'wagtail.embeds',
-    'wagtail.sites',
-    'wagtail.users',
-    'wagtail.snippets',
-    'wagtail.documents',
-    'wagtail.images',
-    'wagtail.search',
-    'wagtail.admin',
-    'wagtail.api.v2',
-    'wagtail.locales',
-    'wagtail.contrib.modeladmin',
-    'wagtail.contrib.routable_page',
-    'wagtail.contrib.simple_translation',
-    'wagtail.contrib.styleguide',
-    'wagtail',
-
-    'rest_framework',
-    'modelcluster',
-    'taggit',
-    'wagtailfontawesome',
-    'debug_toolbar',
-
-    'django.contrib.admin',
-    'django.contrib.auth',
-    'django.contrib.contenttypes',
-    'django.contrib.sessions',
-    'django.contrib.messages',
-    'django.contrib.staticfiles',
-    'django.contrib.sitemaps',
+    "bakerydemo.base",
+    "bakerydemo.blog",
+    "bakerydemo.breads",
+    "bakerydemo.locations",
+    "bakerydemo.search",
+    "wagtail.contrib.search_promotions",
+    "wagtail.contrib.forms",
+    "wagtail.contrib.redirects",
+    "wagtail.embeds",
+    "wagtail.sites",
+    "wagtail.users",
+    "wagtail.snippets",
+    "wagtail.documents",
+    "wagtail.images",
+    "wagtail.search",
+    "wagtail.admin",
+    "wagtail.api.v2",
+    "wagtail.locales",
+    "wagtail.contrib.modeladmin",
+    "wagtail.contrib.routable_page",
+    "wagtail.contrib.simple_translation",
+    "wagtail.contrib.styleguide",
+    "wagtail",
+    "rest_framework",
+    "modelcluster",
+    "taggit",
+    "wagtailfontawesome",
+    "debug_toolbar",
+    "django.contrib.admin",
+    "django.contrib.auth",
+    "django.contrib.contenttypes",
+    "django.contrib.sessions",
+    "django.contrib.messages",
+    "django.contrib.staticfiles",
+    "django.contrib.sitemaps",
 ]
 ]
 
 
 MIDDLEWARE = [
 MIDDLEWARE = [
-    'debug_toolbar.middleware.DebugToolbarMiddleware',
-    'django.middleware.security.SecurityMiddleware',
-    'django.contrib.sessions.middleware.SessionMiddleware',
-    'django.middleware.common.CommonMiddleware',
-    'django.middleware.csrf.CsrfViewMiddleware',
-    'django.contrib.auth.middleware.AuthenticationMiddleware',
-    'django.contrib.messages.middleware.MessageMiddleware',
-    'django.middleware.clickjacking.XFrameOptionsMiddleware',
-
-    'wagtail.contrib.redirects.middleware.RedirectMiddleware',
-
+    "debug_toolbar.middleware.DebugToolbarMiddleware",
+    "django.middleware.security.SecurityMiddleware",
+    "django.contrib.sessions.middleware.SessionMiddleware",
+    "django.middleware.common.CommonMiddleware",
+    "django.middleware.csrf.CsrfViewMiddleware",
+    "django.contrib.auth.middleware.AuthenticationMiddleware",
+    "django.contrib.messages.middleware.MessageMiddleware",
+    "django.middleware.clickjacking.XFrameOptionsMiddleware",
+    "wagtail.contrib.redirects.middleware.RedirectMiddleware",
 ]
 ]
 
 
 DEFAULT_AUTO_FIELD = "django.db.models.AutoField"
 DEFAULT_AUTO_FIELD = "django.db.models.AutoField"
-ROOT_URLCONF = 'bakerydemo.urls'
+ROOT_URLCONF = "bakerydemo.urls"
 
 
 TEMPLATES = [
 TEMPLATES = [
     {
     {
-        'BACKEND': 'django.template.backends.django.DjangoTemplates',
-        'DIRS': ['bakerydemo/templates', ],
-        'APP_DIRS': True,
-        'OPTIONS': {
-            'context_processors': [
-                'django.template.context_processors.debug',
-                'django.template.context_processors.request',
-                'django.contrib.auth.context_processors.auth',
-                'django.contrib.messages.context_processors.messages',
+        "BACKEND": "django.template.backends.django.DjangoTemplates",
+        "DIRS": [
+            "bakerydemo/templates",
+        ],
+        "APP_DIRS": True,
+        "OPTIONS": {
+            "context_processors": [
+                "django.template.context_processors.debug",
+                "django.template.context_processors.request",
+                "django.contrib.auth.context_processors.auth",
+                "django.contrib.messages.context_processors.messages",
             ],
             ],
         },
         },
     },
     },
 ]
 ]
 
 
-WSGI_APPLICATION = 'bakerydemo.wsgi.application'
+WSGI_APPLICATION = "bakerydemo.wsgi.application"
 
 
 
 
 # Database
 # Database
 # https://docs.djangoproject.com/en/3.2/ref/settings/#databases
 # https://docs.djangoproject.com/en/3.2/ref/settings/#databases
 
 
 DATABASES = {
 DATABASES = {
-    'default': {
-        'ENGINE': 'django.db.backends.sqlite3',
-        'NAME': os.path.join(BASE_DIR, 'bakerydemodb')
+    "default": {
+        "ENGINE": "django.db.backends.sqlite3",
+        "NAME": os.path.join(BASE_DIR, "bakerydemodb"),
     }
     }
 }
 }
 
 
@@ -127,16 +124,16 @@ DATABASES = {
 
 
 AUTH_PASSWORD_VALIDATORS = [
 AUTH_PASSWORD_VALIDATORS = [
     {
     {
-        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
+        "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
     },
     },
     {
     {
-        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
+        "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
     },
     },
     {
     {
-        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
+        "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
     },
     },
     {
     {
-        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
+        "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
     },
     },
 ]
 ]
 
 
@@ -144,9 +141,9 @@ AUTH_PASSWORD_VALIDATORS = [
 # Internationalization
 # Internationalization
 # https://docs.djangoproject.com/en/3.2/topics/i18n/
 # https://docs.djangoproject.com/en/3.2/topics/i18n/
 
 
-LANGUAGE_CODE = 'en-us'
+LANGUAGE_CODE = "en-us"
 
 
-TIME_ZONE = 'UTC'
+TIME_ZONE = "UTC"
 
 
 USE_I18N = True
 USE_I18N = True
 
 
@@ -159,28 +156,28 @@ USE_TZ = True
 # https://docs.djangoproject.com/en/3.2/howto/static-files/
 # https://docs.djangoproject.com/en/3.2/howto/static-files/
 
 
 STATICFILES_FINDERS = [
 STATICFILES_FINDERS = [
-    'django.contrib.staticfiles.finders.FileSystemFinder',
-    'django.contrib.staticfiles.finders.AppDirectoriesFinder',
+    "django.contrib.staticfiles.finders.FileSystemFinder",
+    "django.contrib.staticfiles.finders.AppDirectoriesFinder",
 ]
 ]
 
 
 STATICFILES_DIRS = [
 STATICFILES_DIRS = [
-    os.path.join(PROJECT_DIR, 'static'),
+    os.path.join(PROJECT_DIR, "static"),
 ]
 ]
 
 
-STATIC_ROOT = os.path.join(PROJECT_DIR, 'collect_static')
-STATIC_URL = '/static/'
+STATIC_ROOT = os.path.join(PROJECT_DIR, "collect_static")
+STATIC_URL = "/static/"
 
 
-MEDIA_ROOT = os.path.join(PROJECT_DIR, 'media')
-MEDIA_URL = '/media/'
+MEDIA_ROOT = os.path.join(PROJECT_DIR, "media")
+MEDIA_URL = "/media/"
 
 
 # Override in local settings or replace with your own key. Please don't use our demo key in production!
 # Override in local settings or replace with your own key. Please don't use our demo key in production!
-GOOGLE_MAP_API_KEY = 'AIzaSyD31CT9P9KxvNUJOwDq2kcFEIG8ADgaFgw'
+GOOGLE_MAP_API_KEY = "AIzaSyD31CT9P9KxvNUJOwDq2kcFEIG8ADgaFgw"
 
 
 # Use Elasticsearch as the search backend for extra performance and better search results
 # Use Elasticsearch as the search backend for extra performance and better search results
 WAGTAILSEARCH_BACKENDS = {
 WAGTAILSEARCH_BACKENDS = {
-    'default': {
-        'BACKEND': 'wagtail.search.backends.database',
-        'INDEX': 'bakerydemo',
+    "default": {
+        "BACKEND": "wagtail.search.backends.database",
+        "INDEX": "bakerydemo",
     },
     },
 }
 }
 
 

+ 3 - 3
bakerydemo/settings/dev.py

@@ -2,9 +2,9 @@ from .base import *  # noqa: F403, F401
 
 
 DEBUG = True
 DEBUG = True
 
 
-EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
+EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"
 
 
 # WAGTAILADMIN_BASE_URL required for notification emails
 # WAGTAILADMIN_BASE_URL required for notification emails
-WAGTAILADMIN_BASE_URL = 'http://localhost:8000'
+WAGTAILADMIN_BASE_URL = "http://localhost:8000"
 
 
-ALLOWED_HOSTS = ['*']
+ALLOWED_HOSTS = ["*"]

+ 65 - 53
bakerydemo/settings/production.py

@@ -7,120 +7,132 @@ import django_cache_url
 
 
 from .base import *  # noqa: F403
 from .base import *  # noqa: F403
 
 
-DEBUG = os.getenv('DJANGO_DEBUG', 'off') == 'on'
+DEBUG = os.getenv("DJANGO_DEBUG", "off") == "on"
 
 
 # DJANGO_SECRET_KEY *should* be specified in the environment. If it's not, generate an ephemeral key.
 # DJANGO_SECRET_KEY *should* be specified in the environment. If it's not, generate an ephemeral key.
-if 'DJANGO_SECRET_KEY' in os.environ:
-    SECRET_KEY = os.environ['DJANGO_SECRET_KEY']
+if "DJANGO_SECRET_KEY" in os.environ:
+    SECRET_KEY = os.environ["DJANGO_SECRET_KEY"]
 else:
 else:
     # Use if/else rather than a default value to avoid calculating this if we don't need it
     # Use if/else rather than a default value to avoid calculating this if we don't need it
-    print("WARNING: DJANGO_SECRET_KEY not found in os.environ. Generating ephemeral SECRET_KEY.")
-    SECRET_KEY = ''.join([random.SystemRandom().choice(string.printable) for i in range(50)])
+    print(
+        "WARNING: DJANGO_SECRET_KEY not found in os.environ. Generating ephemeral SECRET_KEY."
+    )
+    SECRET_KEY = "".join(
+        [random.SystemRandom().choice(string.printable) for i in range(50)]
+    )
 
 
 # Make sure Django can detect a secure connection properly on Heroku:
 # Make sure Django can detect a secure connection properly on Heroku:
-SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
+SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
 
 
 # Redirect all requests to HTTPS
 # Redirect all requests to HTTPS
-SECURE_SSL_REDIRECT = os.getenv('DJANGO_SECURE_SSL_REDIRECT', 'off') == 'on'
+SECURE_SSL_REDIRECT = os.getenv("DJANGO_SECURE_SSL_REDIRECT", "off") == "on"
 
 
 # Accept all hostnames, since we don't know in advance which hostname will be used for any given Heroku instance.
 # Accept all hostnames, since we don't know in advance which hostname will be used for any given Heroku instance.
 # IMPORTANT: Set this to a real hostname when using this in production!
 # IMPORTANT: Set this to a real hostname when using this in production!
 # See https://docs.djangoproject.com/en/3.2/ref/settings/#allowed-hosts
 # See https://docs.djangoproject.com/en/3.2/ref/settings/#allowed-hosts
-ALLOWED_HOSTS = os.getenv('DJANGO_ALLOWED_HOSTS', '*').split(';')
+ALLOWED_HOSTS = os.getenv("DJANGO_ALLOWED_HOSTS", "*").split(";")
 
 
-EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
+EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"
 
 
 # WAGTAILADMIN_BASE_URL required for notification emails
 # WAGTAILADMIN_BASE_URL required for notification emails
-WAGTAILADMIN_BASE_URL = 'http://localhost:8000'
+WAGTAILADMIN_BASE_URL = "http://localhost:8000"
 
 
 db_from_env = dj_database_url.config(conn_max_age=500)
 db_from_env = dj_database_url.config(conn_max_age=500)
-DATABASES['default'].update(db_from_env)
+DATABASES["default"].update(db_from_env)
 
 
 # AWS creds may be used for S3 and/or Elasticsearch
 # AWS creds may be used for S3 and/or Elasticsearch
-AWS_ACCESS_KEY_ID = os.getenv('AWS_ACCESS_KEY_ID', '')
-AWS_SECRET_ACCESS_KEY = os.getenv('AWS_SECRET_ACCESS_KEY', '')
-AWS_REGION = os.getenv('AWS_REGION', '')
+AWS_ACCESS_KEY_ID = os.getenv("AWS_ACCESS_KEY_ID", "")
+AWS_SECRET_ACCESS_KEY = os.getenv("AWS_SECRET_ACCESS_KEY", "")
+AWS_REGION = os.getenv("AWS_REGION", "")
 
 
 # configure CACHES from CACHE_URL environment variable (defaults to locmem if no CACHE_URL is set)
 # configure CACHES from CACHE_URL environment variable (defaults to locmem if no CACHE_URL is set)
-CACHES = {'default': django_cache_url.config()}
+CACHES = {"default": django_cache_url.config()}
 
 
 # Configure Elasticsearch, if present in os.environ
 # Configure Elasticsearch, if present in os.environ
-ELASTICSEARCH_ENDPOINT = os.getenv('ELASTICSEARCH_ENDPOINT', '')
+ELASTICSEARCH_ENDPOINT = os.getenv("ELASTICSEARCH_ENDPOINT", "")
 
 
 if ELASTICSEARCH_ENDPOINT:
 if ELASTICSEARCH_ENDPOINT:
     from elasticsearch import RequestsHttpConnection
     from elasticsearch import RequestsHttpConnection
+
     WAGTAILSEARCH_BACKENDS = {
     WAGTAILSEARCH_BACKENDS = {
-        'default': {
-            'BACKEND': 'wagtail.search.backends.elasticsearch5',
-            'HOSTS': [{
-                'host': ELASTICSEARCH_ENDPOINT,
-                'port': int(os.getenv('ELASTICSEARCH_PORT', '9200')),
-                'use_ssl': os.getenv('ELASTICSEARCH_USE_SSL', 'off') == 'on',
-                'verify_certs': os.getenv('ELASTICSEARCH_VERIFY_CERTS', 'off') == 'on',
-            }],
-            'OPTIONS': {
-                'connection_class': RequestsHttpConnection,
+        "default": {
+            "BACKEND": "wagtail.search.backends.elasticsearch5",
+            "HOSTS": [
+                {
+                    "host": ELASTICSEARCH_ENDPOINT,
+                    "port": int(os.getenv("ELASTICSEARCH_PORT", "9200")),
+                    "use_ssl": os.getenv("ELASTICSEARCH_USE_SSL", "off") == "on",
+                    "verify_certs": os.getenv("ELASTICSEARCH_VERIFY_CERTS", "off")
+                    == "on",
+                }
+            ],
+            "OPTIONS": {
+                "connection_class": RequestsHttpConnection,
             },
             },
         }
         }
     }
     }
 
 
     if AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY:
     if AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY:
         from aws_requests_auth.aws_auth import AWSRequestsAuth
         from aws_requests_auth.aws_auth import AWSRequestsAuth
-        WAGTAILSEARCH_BACKENDS['default']['HOSTS'][0]['http_auth'] = AWSRequestsAuth(
+
+        WAGTAILSEARCH_BACKENDS["default"]["HOSTS"][0]["http_auth"] = AWSRequestsAuth(
             aws_access_key=AWS_ACCESS_KEY_ID,
             aws_access_key=AWS_ACCESS_KEY_ID,
             aws_secret_access_key=AWS_SECRET_ACCESS_KEY,
             aws_secret_access_key=AWS_SECRET_ACCESS_KEY,
-            aws_token=os.getenv('AWS_SESSION_TOKEN', ''),
+            aws_token=os.getenv("AWS_SESSION_TOKEN", ""),
             aws_host=ELASTICSEARCH_ENDPOINT,
             aws_host=ELASTICSEARCH_ENDPOINT,
             aws_region=AWS_REGION,
             aws_region=AWS_REGION,
-            aws_service='es',
+            aws_service="es",
         )
         )
     elif AWS_REGION:
     elif AWS_REGION:
         # No API keys in the environ, so attempt to discover them with Boto instead, per:
         # No API keys in the environ, so attempt to discover them with Boto instead, per:
         # https://boto3.amazonaws.com/v1/documentation/api/latest/guide/configuration.html#configuring-credentials
         # https://boto3.amazonaws.com/v1/documentation/api/latest/guide/configuration.html#configuring-credentials
         # This may be useful if your credentials are obtained via EC2 instance meta data.
         # This may be useful if your credentials are obtained via EC2 instance meta data.
         from aws_requests_auth.boto_utils import BotoAWSRequestsAuth
         from aws_requests_auth.boto_utils import BotoAWSRequestsAuth
-        WAGTAILSEARCH_BACKENDS['default']['HOSTS'][0]['http_auth'] = BotoAWSRequestsAuth(
+
+        WAGTAILSEARCH_BACKENDS["default"]["HOSTS"][0][
+            "http_auth"
+        ] = BotoAWSRequestsAuth(
             aws_host=ELASTICSEARCH_ENDPOINT,
             aws_host=ELASTICSEARCH_ENDPOINT,
             aws_region=AWS_REGION,
             aws_region=AWS_REGION,
-            aws_service='es',
+            aws_service="es",
         )
         )
 
 
 # Simplified static file serving.
 # Simplified static file serving.
 # https://warehouse.python.org/project/whitenoise/
 # https://warehouse.python.org/project/whitenoise/
 
 
-MIDDLEWARE.append('whitenoise.middleware.WhiteNoiseMiddleware')
-STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
+MIDDLEWARE.append("whitenoise.middleware.WhiteNoiseMiddleware")
+STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage"
 
 
-if 'AWS_STORAGE_BUCKET_NAME' in os.environ:
-    AWS_STORAGE_BUCKET_NAME = os.getenv('AWS_STORAGE_BUCKET_NAME')
-    AWS_S3_CUSTOM_DOMAIN = '%s.s3.amazonaws.com' % AWS_STORAGE_BUCKET_NAME
+if "AWS_STORAGE_BUCKET_NAME" in os.environ:
+    AWS_STORAGE_BUCKET_NAME = os.getenv("AWS_STORAGE_BUCKET_NAME")
+    AWS_S3_CUSTOM_DOMAIN = "%s.s3.amazonaws.com" % AWS_STORAGE_BUCKET_NAME
     AWS_AUTO_CREATE_BUCKET = True
     AWS_AUTO_CREATE_BUCKET = True
 
 
-    INSTALLED_APPS.append('storages')
+    INSTALLED_APPS.append("storages")
     MEDIA_URL = "https://%s/" % AWS_S3_CUSTOM_DOMAIN
     MEDIA_URL = "https://%s/" % AWS_S3_CUSTOM_DOMAIN
-    DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
+    DEFAULT_FILE_STORAGE = "storages.backends.s3boto3.S3Boto3Storage"
 
 
-if 'GS_BUCKET_NAME' in os.environ:
-    GS_BUCKET_NAME = os.getenv('GS_BUCKET_NAME')
-    GS_PROJECT_ID = os.getenv('GS_PROJECT_ID')
-    GS_DEFAULT_ACL = 'publicRead'
+if "GS_BUCKET_NAME" in os.environ:
+    GS_BUCKET_NAME = os.getenv("GS_BUCKET_NAME")
+    GS_PROJECT_ID = os.getenv("GS_PROJECT_ID")
+    GS_DEFAULT_ACL = "publicRead"
     GS_AUTO_CREATE_BUCKET = True
     GS_AUTO_CREATE_BUCKET = True
 
 
-    INSTALLED_APPS.append('storages')
-    DEFAULT_FILE_STORAGE = 'storages.backends.gcloud.GoogleCloudStorage'
+    INSTALLED_APPS.append("storages")
+    DEFAULT_FILE_STORAGE = "storages.backends.gcloud.GoogleCloudStorage"
 
 
 LOGGING = {
 LOGGING = {
-    'version': 1,
-    'disable_existing_loggers': False,
-    'handlers': {
-        'console': {
-            'class': 'logging.StreamHandler',
+    "version": 1,
+    "disable_existing_loggers": False,
+    "handlers": {
+        "console": {
+            "class": "logging.StreamHandler",
         },
         },
     },
     },
-    'loggers': {
-        'django': {
-            'handlers': ['console'],
-            'level': os.getenv('DJANGO_LOG_LEVEL', 'INFO'),
+    "loggers": {
+        "django": {
+            "handlers": ["console"],
+            "level": os.getenv("DJANGO_LOG_LEVEL", "INFO"),
         },
         },
     },
     },
 }
 }

+ 12 - 16
bakerydemo/urls.py

@@ -12,16 +12,13 @@ from bakerydemo.search import views as search_views
 from .api import api_router
 from .api import api_router
 
 
 urlpatterns = [
 urlpatterns = [
-    path('django-admin/', admin.site.urls),
-
-    path('admin/', include(wagtailadmin_urls)),
-    path('documents/', include(wagtaildocs_urls)),
-
-    path('search/', search_views.search, name='search'),
-
-    path('sitemap.xml', sitemap),
-    path('api/v2/', api_router.urls),
-    path('__debug__/', include(debug_toolbar.urls)),
+    path("django-admin/", admin.site.urls),
+    path("admin/", include(wagtailadmin_urls)),
+    path("documents/", include(wagtaildocs_urls)),
+    path("search/", search_views.search, name="search"),
+    path("sitemap.xml", sitemap),
+    path("api/v2/", api_router.urls),
+    path("__debug__/", include(debug_toolbar.urls)),
 ]
 ]
 
 
 
 
@@ -36,18 +33,17 @@ if settings.DEBUG:
     urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
     urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
     urlpatterns += [
     urlpatterns += [
         path(
         path(
-            'favicon.ico', RedirectView.as_view(
-                url=settings.STATIC_URL + 'img/bread-favicon.ico'
-            )
+            "favicon.ico",
+            RedirectView.as_view(url=settings.STATIC_URL + "img/bread-favicon.ico"),
         )
         )
     ]
     ]
 
 
     # Add views for testing 404 and 500 templates
     # Add views for testing 404 and 500 templates
     urlpatterns += [
     urlpatterns += [
-        path('test404/', TemplateView.as_view(template_name='404.html')),
-        path('test500/', TemplateView.as_view(template_name='500.html')),
+        path("test404/", TemplateView.as_view(template_name="404.html")),
+        path("test500/", TemplateView.as_view(template_name="500.html")),
     ]
     ]
 
 
 urlpatterns += [
 urlpatterns += [
-    path('', include(wagtail_urls)),
+    path("", include(wagtail_urls)),
 ]
 ]

+ 1 - 1
bakerydemo/wsgi.py

@@ -13,7 +13,7 @@ import dotenv
 from django.core.wsgi import get_wsgi_application
 from django.core.wsgi import get_wsgi_application
 
 
 
 
-dotenv.read_dotenv(os.path.join(os.path.dirname(os.path.dirname(__file__)), '.env'))
+dotenv.read_dotenv(os.path.join(os.path.dirname(os.path.dirname(__file__)), ".env"))
 
 
 os.environ.setdefault("DJANGO_SETTINGS_MODULE", "bakerydemo.settings.dev")
 os.environ.setdefault("DJANGO_SETTINGS_MODULE", "bakerydemo.settings.dev")