diff --git a/bakerydemo/api.py b/bakerydemo/api.py index 2d9bc94..63c946f 100644 --- a/bakerydemo/api.py +++ b/bakerydemo/api.py @@ -4,12 +4,12 @@ from wagtail.images.api.v2.views import ImagesAPIViewSet from wagtail.documents.api.v2.views import DocumentsAPIViewSet # 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. # The first parameter is the name of the endpoint (eg. pages, images). This # is used in the URL of the endpoint # 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) diff --git a/bakerydemo/base/blocks.py b/bakerydemo/base/blocks.py index 7543640..132c4b1 100644 --- a/bakerydemo/base/blocks.py +++ b/bakerydemo/base/blocks.py @@ -1,7 +1,12 @@ from wagtail.images.blocks import ImageChooserBlock from wagtail.embeds.blocks import EmbedBlock 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 attribution data """ + image = ImageChooserBlock(required=True) caption = CharBlock(required=False) attribution = CharBlock(required=False) class Meta: - icon = 'image' + icon = "image" 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 """ + 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: icon = "title" @@ -40,9 +51,9 @@ class BlockQuote(StructBlock): """ Custom `StructBlock` that allows the user to attribute a quote to the author """ + 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: icon = "fa-quote-left" @@ -54,14 +65,15 @@ class BaseStreamBlock(StreamBlock): """ Define the custom blocks that `StreamField` will utilize """ + heading_block = HeadingBlock() paragraph_block = RichTextBlock( - icon="fa-paragraph", - template="blocks/paragraph_block.html" + icon="fa-paragraph", template="blocks/paragraph_block.html" ) image_block = ImageBlock() block_quote = BlockQuote() 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", - template="blocks/embed_block.html") + template="blocks/embed_block.html", + ) diff --git a/bakerydemo/base/management/commands/load_initial_data.py b/bakerydemo/base/management/commands/load_initial_data.py index 130bae1..64998cd 100644 --- a/bakerydemo/base/management/commands/load_initial_data.py +++ b/bakerydemo/base/management/commands/load_initial_data.py @@ -18,27 +18,29 @@ class Command(BaseCommand): """ directories, file_names = local_storage.listdir(path) for directory in directories: - self._copy_files(local_storage, path + directory + '/') + self._copy_files(local_storage, path + directory + "/") for file_name in file_names: with local_storage.open(path + file_name) as file_: default_storage.save(path + file_name, file_) 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...") - 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 # 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..." + ) diff --git a/bakerydemo/base/migrations/0001_initial.py b/bakerydemo/base/migrations/0001_initial.py index 207d8f2..4c32ad3 100644 --- a/bakerydemo/base/migrations/0001_initial.py +++ b/bakerydemo/base/migrations/0001_initial.py @@ -16,146 +16,783 @@ class Migration(migrations.Migration): initial = True 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 = [ migrations.CreateModel( - name='FooterText', + name="FooterText", 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={ - 'verbose_name_plural': 'Footer Text', + "verbose_name_plural": "Footer Text", }, ), migrations.CreateModel( - name='FormField', + name="FormField", 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={ - 'ordering': ['sort_order'], - 'abstract': False, + "ordering": ["sort_order"], + "abstract": False, }, ), migrations.CreateModel( - name='FormPage', + name="FormPage", 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={ - 'abstract': False, + "abstract": False, }, - bases=('wagtailcore.page',), + bases=("wagtailcore.page",), ), migrations.CreateModel( - name='GalleryPage', + name="GalleryPage", 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={ - 'abstract': False, + "abstract": False, }, - bases=('wagtailcore.page', models.Model), + bases=("wagtailcore.page", models.Model), ), migrations.CreateModel( - name='HomePage', + name="HomePage", 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={ - 'abstract': False, + "abstract": False, }, - bases=('wagtailcore.page',), + bases=("wagtailcore.page",), ), migrations.CreateModel( - name='People', + name="People", 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={ - 'verbose_name_plural': 'People', - 'verbose_name': 'Person', + "verbose_name_plural": "People", + "verbose_name": "Person", }, ), migrations.CreateModel( - name='StandardPage', + name="StandardPage", 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={ - 'abstract': False, + "abstract": False, }, - bases=('wagtailcore.page', models.Model), + bases=("wagtailcore.page", models.Model), ), 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( - 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( - 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( - 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( - 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( - 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( - 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", + ), ), ] diff --git a/bakerydemo/base/migrations/0002_auto_20170329_0055.py b/bakerydemo/base/migrations/0002_auto_20170329_0055.py index 765b37d..db09275 100644 --- a/bakerydemo/base/migrations/0002_auto_20170329_0055.py +++ b/bakerydemo/base/migrations/0002_auto_20170329_0055.py @@ -12,28 +12,342 @@ import wagtail.images.blocks class Migration(migrations.Migration): dependencies = [ - ('base', '0001_initial'), + ("base", "0001_initial"), ] operations = [ 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( - 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( - 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( - 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", + ), ), ] diff --git a/bakerydemo/base/migrations/0003_auto_20170823_1127.py b/bakerydemo/base/migrations/0003_auto_20170823_1127.py index 007297d..d47595b 100644 --- a/bakerydemo/base/migrations/0003_auto_20170823_1127.py +++ b/bakerydemo/base/migrations/0003_auto_20170823_1127.py @@ -8,13 +8,30 @@ from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('base', '0002_auto_20170329_0055'), + ("base", "0002_auto_20170329_0055"), ] operations = [ 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", + ), ), ] diff --git a/bakerydemo/base/migrations/0004_auto_20180522_1856.py b/bakerydemo/base/migrations/0004_auto_20180522_1856.py index 87e3c16..ac0f3e8 100644 --- a/bakerydemo/base/migrations/0004_auto_20180522_1856.py +++ b/bakerydemo/base/migrations/0004_auto_20180522_1856.py @@ -7,18 +7,43 @@ import django.db.models.deletion class Migration(migrations.Migration): dependencies = [ - ('base', '0003_auto_20170823_1127'), + ("base", "0003_auto_20170823_1127"), ] operations = [ 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( - 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", + ), ), ] diff --git a/bakerydemo/base/migrations/0005_formfield_clean_name.py b/bakerydemo/base/migrations/0005_formfield_clean_name.py index 0165c46..94629ea 100644 --- a/bakerydemo/base/migrations/0005_formfield_clean_name.py +++ b/bakerydemo/base/migrations/0005_formfield_clean_name.py @@ -6,13 +6,19 @@ from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('base', '0004_auto_20180522_1856'), + ("base", "0004_auto_20180522_1856"), ] operations = [ 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", + ), ), ] diff --git a/bakerydemo/base/migrations/0006_char_field_remove_null.py b/bakerydemo/base/migrations/0006_char_field_remove_null.py index d3be5d6..70304a4 100644 --- a/bakerydemo/base/migrations/0006_char_field_remove_null.py +++ b/bakerydemo/base/migrations/0006_char_field_remove_null.py @@ -6,32 +6,52 @@ from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('base', '0005_formfield_clean_name'), + ("base", "0005_formfield_clean_name"), ] operations = [ 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, ), 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, ), 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, ), 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, ), ] diff --git a/bakerydemo/base/migrations/0007_alter_formfield_choices_and_more.py b/bakerydemo/base/migrations/0007_alter_formfield_choices_and_more.py index 6638f6f..d7dbe9a 100644 --- a/bakerydemo/base/migrations/0007_alter_formfield_choices_and_more.py +++ b/bakerydemo/base/migrations/0007_alter_formfield_choices_and_more.py @@ -7,28 +7,44 @@ import wagtail.contrib.forms.models class Migration(migrations.Migration): dependencies = [ - ('base', '0006_char_field_remove_null'), + ("base", "0006_char_field_remove_null"), ] operations = [ 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( - 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( - 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( - 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", + ), ), ] diff --git a/bakerydemo/base/migrations/0008_use_json_field_for_body_streamfield.py b/bakerydemo/base/migrations/0008_use_json_field_for_body_streamfield.py index 3a8615e..d2d2b14 100644 --- a/bakerydemo/base/migrations/0008_use_json_field_for_body_streamfield.py +++ b/bakerydemo/base/migrations/0008_use_json_field_for_body_streamfield.py @@ -10,28 +10,346 @@ import wagtail.images.blocks class Migration(migrations.Migration): dependencies = [ - ('base', '0007_alter_formfield_choices_and_more'), + ("base", "0007_alter_formfield_choices_and_more"), ] operations = [ 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( - 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( - 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( - 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", + ), ), ] diff --git a/bakerydemo/base/models.py b/bakerydemo/base/models.py index cfec7af..6137f57 100644 --- a/bakerydemo/base/models.py +++ b/bakerydemo/base/models.py @@ -34,32 +34,38 @@ class People(index.Indexed, ClusterableModel): to the database. https://github.com/wagtail/django-modelcluster """ + first_name = models.CharField("First name", max_length=254) last_name = models.CharField("Last name", max_length=254) job_title = models.CharField("Job title", max_length=254) image = models.ForeignKey( - 'wagtailimages.Image', + "wagtailimages.Image", null=True, blank=True, on_delete=models.SET_NULL, - related_name='+' + related_name="+", ) 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 = [ - index.SearchField('first_name'), - index.SearchField('last_name'), + index.SearchField("first_name"), + index.SearchField("last_name"), ] @property @@ -67,16 +73,16 @@ class People(index.Indexed, ClusterableModel): # Returns an empty string if there is no profile pic or the rendition # file can't be found. 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:' - return '' + return "" def __str__(self): - return '{} {}'.format(self.first_name, self.last_name) + return "{} {}".format(self.first_name, self.last_name) class Meta: - verbose_name = 'Person' - verbose_name_plural = 'People' + verbose_name = "Person" + verbose_name_plural = "People" @register_snippet @@ -87,17 +93,18 @@ class FooterText(models.Model): accessible on the template via a template tag defined in base/templatetags/ navigation_tags.py """ + body = RichTextField() panels = [ - FieldPanel('body'), + FieldPanel("body"), ] def __str__(self): return "Footer text" class Meta: - verbose_name_plural = 'Footer Text' + verbose_name_plural = "Footer Text" class StandardPage(Page): @@ -107,24 +114,22 @@ class StandardPage(Page): 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( - 'wagtailimages.Image', + "wagtailimages.Image", null=True, blank=True, 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( BaseStreamBlock(), verbose_name="Page body", blank=True, use_json_field=True ) 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 image = models.ForeignKey( - 'wagtailimages.Image', + "wagtailimages.Image", null=True, blank=True, on_delete=models.SET_NULL, - related_name='+', - help_text='Homepage image' + related_name="+", + help_text="Homepage image", ) 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( - verbose_name='Hero CTA', + verbose_name="Hero CTA", 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( - 'wagtailcore.Page', + "wagtailcore.Page", null=True, blank=True, 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 = 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_image = models.ForeignKey( - 'wagtailimages.Image', + "wagtailimages.Image", null=True, blank=True, on_delete=models.SET_NULL, - related_name='+', - help_text='Promo image' + related_name="+", + help_text="Promo image", ) 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( - 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 @@ -198,82 +201,94 @@ class HomePage(Page): # Each list their children items that we access via the children function # that we define on the individual Page models e.g. BlogIndexPage 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( - 'wagtailcore.Page', + "wagtailcore.Page", null=True, blank=True, 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( - 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( - 'wagtailcore.Page', + "wagtailcore.Page", null=True, blank=True, 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( - 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( - 'wagtailcore.Page', + "wagtailcore.Page", null=True, blank=True, 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 + [ - 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): @@ -288,35 +303,32 @@ class GalleryPage(Page): 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( - 'wagtailimages.Image', + "wagtailimages.Image", null=True, blank=True, 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( BaseStreamBlock(), verbose_name="Page body", blank=True, use_json_field=True ) collection = models.ForeignKey( Collection, - limit_choices_to=~models.Q(name__in=['Root']), + limit_choices_to=~models.Q(name__in=["Root"]), null=True, blank=True, 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 + [ - 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 @@ -333,16 +345,17 @@ class FormField(AbstractFormField): can read more about Wagtail forms at: 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): image = models.ForeignKey( - 'wagtailimages.Image', + "wagtailimages.Image", null=True, blank=True, on_delete=models.SET_NULL, - related_name='+' + related_name="+", ) body = StreamField(BaseStreamBlock(), use_json_field=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 # related_name value 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", + ), ] diff --git a/bakerydemo/base/templatetags/gallery_tags.py b/bakerydemo/base/templatetags/gallery_tags.py index 488c7a8..0229c13 100644 --- a/bakerydemo/base/templatetags/gallery_tags.py +++ b/bakerydemo/base/templatetags/gallery_tags.py @@ -6,11 +6,11 @@ register = template.Library() # 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): images = Image.objects.filter(collection=gallery) return { - 'images': images, - 'request': context['request'], + "images": images, + "request": context["request"], } diff --git a/bakerydemo/base/templatetags/navigation_tags.py b/bakerydemo/base/templatetags/navigation_tags.py index c7f10a1..6f824ae 100644 --- a/bakerydemo/base/templatetags/navigation_tags.py +++ b/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 # defined else will return an object attribute error ('str' object has no # 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): @@ -31,13 +31,13 @@ def has_children(page): def is_active(page, current_page): # 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 # The has_menu_children method is necessary because the Foundation menu requires # 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): menuitems = parent.get_children().live().in_menu() 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 # engine can pass an empty string to calling_page # 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 { - '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 - 'request': context['request'], + "request": context["request"], } # 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): menuitems_children = parent.get_children() 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 # engine can pass an empty string to calling_page # 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() 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 - '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): - self = context.get('self') + self = context.get("self") if self is None or self.depth <= 2: # When on the home page, displaying breadcrumbs is irrelevant. ancestors = () 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 { - '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): footer_text = "" if FooterText.objects.first() is not None: footer_text = FooterText.objects.first().body return { - 'footer_text': footer_text, + "footer_text": footer_text, } diff --git a/bakerydemo/base/wagtail_hooks.py b/bakerydemo/base/wagtail_hooks.py index 9ebb908..7211c8a 100644 --- a/bakerydemo/base/wagtail_hooks.py +++ b/bakerydemo/base/wagtail_hooks.py @@ -1,10 +1,13 @@ from wagtail.contrib.modeladmin.options import ( - ModelAdmin, ModelAdminGroup, modeladmin_register) + ModelAdmin, + ModelAdminGroup, + modeladmin_register, +) from bakerydemo.breads.models import Country, BreadIngredient, BreadType from bakerydemo.base.models import People, FooterText -''' +""" N.B. To see what icons are available for use in Wagtail menus and StreamField block types, 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 font-awesome icon set is available to you. Options are at https://fontawesome.com/icons . -''' +""" class BreadIngredientAdmin(ModelAdmin): # These stub classes allow us to put various models into the custom "Wagtail Bakery" menu item # rather than under the default Snippets section. model = BreadIngredient - search_fields = ('name', ) + search_fields = ("name",) class BreadTypeAdmin(ModelAdmin): model = BreadType - search_fields = ('title', ) + search_fields = ("title",) class BreadCountryAdmin(ModelAdmin): model = Country - search_fields = ('title', ) + search_fields = ("title",) 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) items = (BreadIngredientAdmin, BreadTypeAdmin, BreadCountryAdmin) class PeopleModelAdmin(ModelAdmin): 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 class FooterTextAdmin(ModelAdmin): model = FooterText - search_fields = ('body',) + search_fields = ("body",) 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) items = (PeopleModelAdmin, FooterTextAdmin) diff --git a/bakerydemo/blog/migrations/0001_initial.py b/bakerydemo/blog/migrations/0001_initial.py index 4f536ca..24d7eb5 100644 --- a/bakerydemo/blog/migrations/0001_initial.py +++ b/bakerydemo/blog/migrations/0001_initial.py @@ -18,68 +18,348 @@ class Migration(migrations.Migration): initial = True 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 = [ migrations.CreateModel( - name='BlogIndexPage', + name="BlogIndexPage", 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={ - '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( - name='BlogPage', + name="BlogPage", 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={ - 'abstract': False, + "abstract": False, }, - bases=('wagtailcore.page', models.Model), + bases=("wagtailcore.page", models.Model), ), migrations.CreateModel( - name='BlogPageTag', + name="BlogPageTag", 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={ - 'abstract': False, + "abstract": False, }, ), migrations.CreateModel( - name='BlogPeopleRelationship', + name="BlogPeopleRelationship", 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={ - 'ordering': ['sort_order'], - 'abstract': False, + "ordering": ["sort_order"], + "abstract": False, }, ), 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", + ), ), ] diff --git a/bakerydemo/blog/migrations/0002_remove_blogindexpage_body.py b/bakerydemo/blog/migrations/0002_remove_blogindexpage_body.py index 349b0f0..7620cea 100644 --- a/bakerydemo/blog/migrations/0002_remove_blogindexpage_body.py +++ b/bakerydemo/blog/migrations/0002_remove_blogindexpage_body.py @@ -8,12 +8,12 @@ from django.db import migrations class Migration(migrations.Migration): dependencies = [ - ('blog', '0001_initial'), + ("blog", "0001_initial"), ] operations = [ migrations.RemoveField( - model_name='blogindexpage', - name='body', + model_name="blogindexpage", + name="body", ), ] diff --git a/bakerydemo/blog/migrations/0003_auto_20170329_0055.py b/bakerydemo/blog/migrations/0003_auto_20170329_0055.py index 8357fe3..ab8b74b 100644 --- a/bakerydemo/blog/migrations/0003_auto_20170329_0055.py +++ b/bakerydemo/blog/migrations/0003_auto_20170329_0055.py @@ -12,13 +12,92 @@ import wagtail.images.blocks class Migration(migrations.Migration): dependencies = [ - ('blog', '0002_remove_blogindexpage_body'), + ("blog", "0002_remove_blogindexpage_body"), ] operations = [ 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", + ), ), ] diff --git a/bakerydemo/blog/migrations/0004_alter_blogpagetag_tag.py b/bakerydemo/blog/migrations/0004_alter_blogpagetag_tag.py index c1c34e9..acb6007 100644 --- a/bakerydemo/blog/migrations/0004_alter_blogpagetag_tag.py +++ b/bakerydemo/blog/migrations/0004_alter_blogpagetag_tag.py @@ -7,14 +7,18 @@ import django.db.models.deletion class Migration(migrations.Migration): 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 = [ 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", + ), ), ] diff --git a/bakerydemo/blog/migrations/0005_use_json_field_for_body_streamfield.py b/bakerydemo/blog/migrations/0005_use_json_field_for_body_streamfield.py index 7babb8e..7325d38 100644 --- a/bakerydemo/blog/migrations/0005_use_json_field_for_body_streamfield.py +++ b/bakerydemo/blog/migrations/0005_use_json_field_for_body_streamfield.py @@ -10,13 +10,93 @@ import wagtail.images.blocks class Migration(migrations.Migration): dependencies = [ - ('blog', '0004_alter_blogpagetag_tag'), + ("blog", "0004_alter_blogpagetag_tag"), ] operations = [ 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", + ), ), ] diff --git a/bakerydemo/blog/models.py b/bakerydemo/blog/models.py index 46f6a6b..0c2461c 100644 --- a/bakerydemo/blog/models.py +++ b/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 the ParentalKey and ForeignKey """ + 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( - '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): @@ -43,7 +42,10 @@ class BlogPageTag(TaggedItemBase): 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 """ - 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): @@ -54,40 +56,37 @@ class BlogPage(Page): ParentalKey's related_name in BlogPeopleRelationship. More docs: 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( - 'wagtailimages.Image', + "wagtailimages.Image", null=True, blank=True, 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( BaseStreamBlock(), verbose_name="Page body", blank=True, use_json_field=True ) subtitle = models.CharField(blank=True, max_length=255) 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 + [ - 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( - '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 + [ - index.SearchField('body'), + index.SearchField("body"), ] def authors(self): @@ -98,9 +97,7 @@ class BlogPage(Page): with a loop on the template. If we tried to access the blog_person_ 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 @@ -113,15 +110,13 @@ class BlogPage(Page): """ tags = self.tags.all() 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 # 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. # 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 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( - 'wagtailimages.Image', + "wagtailimages.Image", null=True, blank=True, 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 + [ - FieldPanel('introduction', classname="full"), - FieldPanel('image'), + FieldPanel("introduction", classname="full"), + FieldPanel("image"), ] # 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 # 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 def get_context(self, 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 # 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. # More information on RoutablePages is at # 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): try: @@ -189,11 +183,8 @@ class BlogIndexPage(RoutablePageMixin, Page): return redirect(self.url) 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): # Needed for previews to work diff --git a/bakerydemo/breads/migrations/0001_initial.py b/bakerydemo/breads/migrations/0001_initial.py index fc48c46..b685e31 100644 --- a/bakerydemo/breads/migrations/0001_initial.py +++ b/bakerydemo/breads/migrations/0001_initial.py @@ -16,84 +16,336 @@ class Migration(migrations.Migration): initial = True 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 = [ migrations.CreateModel( - name='BreadIngredient', + name="BreadIngredient", 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={ - 'verbose_name_plural': 'Bread ingredients', + "verbose_name_plural": "Bread ingredients", }, ), migrations.CreateModel( - name='BreadPage', + name="BreadPage", 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={ - 'abstract': False, + "abstract": False, }, - bases=('wagtailcore.page', models.Model), + bases=("wagtailcore.page", models.Model), ), migrations.CreateModel( - name='BreadsIndexPage', + name="BreadsIndexPage", 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={ - 'abstract': False, + "abstract": False, }, - bases=('wagtailcore.page', models.Model), + bases=("wagtailcore.page", models.Model), ), migrations.CreateModel( - name='BreadType', + name="BreadType", 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={ - 'verbose_name_plural': 'Bread types', + "verbose_name_plural": "Bread types", }, ), migrations.CreateModel( - name='Country', + name="Country", 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={ - 'verbose_name_plural': 'Countries of Origin', + "verbose_name_plural": "Countries of Origin", }, ), 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( - 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( - 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( - 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", + ), ), ] diff --git a/bakerydemo/breads/migrations/0002_remove_breadsindexpage_body.py b/bakerydemo/breads/migrations/0002_remove_breadsindexpage_body.py index 7afc381..cdfd07b 100644 --- a/bakerydemo/breads/migrations/0002_remove_breadsindexpage_body.py +++ b/bakerydemo/breads/migrations/0002_remove_breadsindexpage_body.py @@ -8,12 +8,12 @@ from django.db import migrations class Migration(migrations.Migration): dependencies = [ - ('breads', '0001_initial'), + ("breads", "0001_initial"), ] operations = [ migrations.RemoveField( - model_name='breadsindexpage', - name='body', + model_name="breadsindexpage", + name="body", ), ] diff --git a/bakerydemo/breads/migrations/0003_auto_20170329_0055.py b/bakerydemo/breads/migrations/0003_auto_20170329_0055.py index 6f3ee2c..35d599b 100644 --- a/bakerydemo/breads/migrations/0003_auto_20170329_0055.py +++ b/bakerydemo/breads/migrations/0003_auto_20170329_0055.py @@ -12,13 +12,92 @@ import wagtail.images.blocks class Migration(migrations.Migration): dependencies = [ - ('breads', '0002_remove_breadsindexpage_body'), + ("breads", "0002_remove_breadsindexpage_body"), ] operations = [ 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", + ), ), ] diff --git a/bakerydemo/breads/migrations/0004_use_json_field_for_body_streamfield.py b/bakerydemo/breads/migrations/0004_use_json_field_for_body_streamfield.py index c6d2b6a..33915a1 100644 --- a/bakerydemo/breads/migrations/0004_use_json_field_for_body_streamfield.py +++ b/bakerydemo/breads/migrations/0004_use_json_field_for_body_streamfield.py @@ -10,13 +10,93 @@ import wagtail.images.blocks class Migration(migrations.Migration): dependencies = [ - ('breads', '0003_auto_20170329_0055'), + ("breads", "0003_auto_20170329_0055"), ] operations = [ 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", + ), ), ] diff --git a/bakerydemo/breads/models.py b/bakerydemo/breads/models.py index c828238..b6c423c 100644 --- a/bakerydemo/breads/models.py +++ b/bakerydemo/breads/models.py @@ -4,9 +4,7 @@ from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger 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.models import Page 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 https://docs.wagtail.org/en/stable/getting_started/tutorial.html#categories """ + name = models.CharField(max_length=255) panels = [ - FieldPanel('name'), + FieldPanel("name"), ] def __str__(self): return self.name class Meta: - verbose_name_plural = 'Bread ingredients' + verbose_name_plural = "Bread ingredients" @register_snippet @@ -72,7 +71,7 @@ class BreadType(models.Model): title = models.CharField(max_length=255) panels = [ - FieldPanel('title'), + FieldPanel("title"), ] def __str__(self): @@ -86,16 +85,15 @@ class BreadPage(Page): """ 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( - 'wagtailimages.Image', + "wagtailimages.Image", null=True, blank=True, 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( 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 # collision. bread_type = models.ForeignKey( - 'breads.BreadType', + "breads.BreadType", null=True, blank=True, on_delete=models.SET_NULL, - related_name='+' + related_name="+", ) - ingredients = ParentalManyToManyField('BreadIngredient', blank=True) + ingredients = ParentalManyToManyField("BreadIngredient", blank=True) 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( [ FieldPanel( - 'ingredients', + "ingredients", widget=forms.CheckboxSelectMultiple, ), ], heading="Additional Metadata", - classname="collapsible collapsed" + classname="collapsible collapsed", ), ] search_fields = Page.search_fields + [ - index.SearchField('body'), + index.SearchField("body"), ] - parent_page_types = ['BreadsIndexPage'] + parent_page_types = ["BreadsIndexPage"] class BreadsIndexPage(Page): @@ -155,32 +153,30 @@ class BreadsIndexPage(Page): 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( - 'wagtailimages.Image', + "wagtailimages.Image", null=True, blank=True, 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 + [ - FieldPanel('introduction', classname="full"), - FieldPanel('image'), + FieldPanel("introduction", classname="full"), + FieldPanel("image"), ] # Can only have BreadPage children - subpage_types = ['BreadPage'] + subpage_types = ["BreadPage"] # Returns a queryset of BreadPage objects that are live, that are direct # descendants of this index page with most recent first 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 # 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 # method on the model rather than within a view function def paginate(self, request, *args): - page = request.GET.get('page') + page = request.GET.get("page") paginator = Paginator(self.get_breads(), 12) try: pages = paginator.page(page) @@ -210,6 +206,6 @@ class BreadsIndexPage(Page): # BreadPage objects (get_breads) are passed through pagination breads = self.paginate(request, self.get_breads()) - context['breads'] = breads + context["breads"] = breads return context diff --git a/bakerydemo/locations/choices.py b/bakerydemo/locations/choices.py index 9184578..5b7052e 100644 --- a/bakerydemo/locations/choices.py +++ b/bakerydemo/locations/choices.py @@ -1,10 +1,9 @@ - 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"), ) diff --git a/bakerydemo/locations/migrations/0001_initial.py b/bakerydemo/locations/migrations/0001_initial.py index 2edcf90..f875f6d 100644 --- a/bakerydemo/locations/migrations/0001_initial.py +++ b/bakerydemo/locations/migrations/0001_initial.py @@ -17,57 +17,324 @@ class Migration(migrations.Migration): initial = True 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 = [ migrations.CreateModel( - name='LocationOperatingHours', + name="LocationOperatingHours", 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={ - 'ordering': ['sort_order'], - 'abstract': False, + "ordering": ["sort_order"], + "abstract": False, }, ), migrations.CreateModel( - name='LocationPage', + name="LocationPage", 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={ - 'abstract': False, + "abstract": False, }, - bases=('wagtailcore.page', models.Model), + bases=("wagtailcore.page", models.Model), ), migrations.CreateModel( - name='LocationsIndexPage', + name="LocationsIndexPage", 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={ - 'abstract': False, + "abstract": False, }, - bases=('wagtailcore.page', models.Model), + bases=("wagtailcore.page", models.Model), ), 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", + ), ), ] diff --git a/bakerydemo/locations/migrations/0002_remove_locationsindexpage_body.py b/bakerydemo/locations/migrations/0002_remove_locationsindexpage_body.py index 6068157..48646d3 100644 --- a/bakerydemo/locations/migrations/0002_remove_locationsindexpage_body.py +++ b/bakerydemo/locations/migrations/0002_remove_locationsindexpage_body.py @@ -8,12 +8,12 @@ from django.db import migrations class Migration(migrations.Migration): dependencies = [ - ('locations', '0001_initial'), + ("locations", "0001_initial"), ] operations = [ migrations.RemoveField( - model_name='locationsindexpage', - name='body', + model_name="locationsindexpage", + name="body", ), ] diff --git a/bakerydemo/locations/migrations/0003_auto_20170329_0055.py b/bakerydemo/locations/migrations/0003_auto_20170329_0055.py index 59f5541..e4e48f1 100644 --- a/bakerydemo/locations/migrations/0003_auto_20170329_0055.py +++ b/bakerydemo/locations/migrations/0003_auto_20170329_0055.py @@ -12,13 +12,92 @@ import wagtail.images.blocks class Migration(migrations.Migration): dependencies = [ - ('locations', '0002_remove_locationsindexpage_body'), + ("locations", "0002_remove_locationsindexpage_body"), ] operations = [ 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", + ), ), ] diff --git a/bakerydemo/locations/migrations/0004_auto_20190912_1149.py b/bakerydemo/locations/migrations/0004_auto_20190912_1149.py index b30d6f4..edea3e1 100644 --- a/bakerydemo/locations/migrations/0004_auto_20190912_1149.py +++ b/bakerydemo/locations/migrations/0004_auto_20190912_1149.py @@ -6,13 +6,17 @@ from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('locations', '0003_auto_20170329_0055'), + ("locations", "0003_auto_20170329_0055"), ] operations = [ 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?", + ), ), ] diff --git a/bakerydemo/locations/migrations/0005_use_json_field_for_body_streamfield.py b/bakerydemo/locations/migrations/0005_use_json_field_for_body_streamfield.py index 0fcfedc..9ce4f44 100644 --- a/bakerydemo/locations/migrations/0005_use_json_field_for_body_streamfield.py +++ b/bakerydemo/locations/migrations/0005_use_json_field_for_body_streamfield.py @@ -10,13 +10,93 @@ import wagtail.images.blocks class Migration(migrations.Migration): dependencies = [ - ('locations', '0004_auto_20190912_1149'), + ("locations", "0004_auto_20190912_1149"), ] operations = [ 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", + ), ), ] diff --git a/bakerydemo/locations/models.py b/bakerydemo/locations/models.py index 1cb2cf4..c810a16 100644 --- a/bakerydemo/locations/models.py +++ b/bakerydemo/locations/models.py @@ -20,30 +20,18 @@ class OperatingHours(models.Model): 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?", - 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 = [ - FieldPanel('day'), - FieldPanel('opening_time'), - FieldPanel('closing_time'), - FieldPanel('closed'), + FieldPanel("day"), + FieldPanel("opening_time"), + FieldPanel("closing_time"), + FieldPanel("closed"), ] class Meta: @@ -51,19 +39,14 @@ class OperatingHours(models.Model): def __str__(self): if self.opening_time: - opening = self.opening_time.strftime('%H:%M') + opening = self.opening_time.strftime("%H:%M") else: - opening = '--' + opening = "--" if self.closing_time: - closed = self.closing_time.strftime('%H:%M') + closed = self.closing_time.strftime("%H:%M") 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): @@ -75,10 +58,9 @@ class LocationOperatingHours(Orderable, OperatingHours): relate the two objects to one another. We use the ParentalKey's related_ name to access it from the LocationPage admin """ + 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) """ - 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( - 'wagtailimages.Image', + "wagtailimages.Image", null=True, blank=True, 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 - subpage_types = ['LocationPage'] + subpage_types = ["LocationPage"] # Allows children of this indexpage to be accessible via the indexpage # 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 def get_context(self, 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 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. """ - 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( - 'wagtailimages.Image', + "wagtailimages.Image", null=True, blank=True, 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( BaseStreamBlock(), verbose_name="Page body", blank=True, use_json_field=True @@ -145,31 +125,31 @@ class LocationPage(Page): lat_long = models.CharField( max_length=36, 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=[ 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_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 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): @@ -184,12 +164,12 @@ class LocationPage(Page): def is_open(self): now = datetime.now() current_time = now.time() - current_day = now.strftime('%a').upper() + current_day = now.strftime("%a").upper() try: self.operating_hours.get( day=current_day, opening_time__lte=current_time, - closing_time__gte=current_time + closing_time__gte=current_time, ) return True except LocationOperatingHours.DoesNotExist: @@ -199,10 +179,10 @@ class LocationPage(Page): # the latitude, longitude and map API key to render the map def get_context(self, 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 # Can only be placed under a LocationsIndexPage object - parent_page_types = ['LocationsIndexPage'] + parent_page_types = ["LocationsIndexPage"] diff --git a/bakerydemo/search/views.py b/bakerydemo/search/views.py index 3ffcd29..9d0715f 100644 --- a/bakerydemo/search/views.py +++ b/bakerydemo/search/views.py @@ -12,9 +12,9 @@ from bakerydemo.locations.models import LocationPage def search(request): # Search - search_query = request.GET.get('q', None) + search_query = request.GET.get("q", None) 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 # https://docs.wagtail.org/en/stable/topics/search/backends.html # like this: @@ -44,7 +44,7 @@ def search(request): search_results = Page.objects.none() # Pagination - page = request.GET.get('page', 1) + page = request.GET.get("page", 1) paginator = Paginator(search_results, 10) try: search_results = paginator.page(page) @@ -53,7 +53,11 @@ def search(request): except EmptyPage: 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, + }, + ) diff --git a/bakerydemo/settings/base.py b/bakerydemo/settings/base.py index 8181718..68a2829 100644 --- a/bakerydemo/settings/base.py +++ b/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/ # 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! DEBUG = True @@ -35,89 +35,86 @@ ALLOWED_HOSTS = [] # Application definition 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 = [ - '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" -ROOT_URLCONF = 'bakerydemo.urls' +ROOT_URLCONF = "bakerydemo.urls" 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 # https://docs.djangoproject.com/en/3.2/ref/settings/#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 = [ { - '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 # 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 @@ -159,28 +156,28 @@ USE_TZ = True # https://docs.djangoproject.com/en/3.2/howto/static-files/ STATICFILES_FINDERS = [ - 'django.contrib.staticfiles.finders.FileSystemFinder', - 'django.contrib.staticfiles.finders.AppDirectoriesFinder', + "django.contrib.staticfiles.finders.FileSystemFinder", + "django.contrib.staticfiles.finders.AppDirectoriesFinder", ] 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! -GOOGLE_MAP_API_KEY = 'AIzaSyD31CT9P9KxvNUJOwDq2kcFEIG8ADgaFgw' +GOOGLE_MAP_API_KEY = "AIzaSyD31CT9P9KxvNUJOwDq2kcFEIG8ADgaFgw" # Use Elasticsearch as the search backend for extra performance and better search results WAGTAILSEARCH_BACKENDS = { - 'default': { - 'BACKEND': 'wagtail.search.backends.database', - 'INDEX': 'bakerydemo', + "default": { + "BACKEND": "wagtail.search.backends.database", + "INDEX": "bakerydemo", }, } diff --git a/bakerydemo/settings/dev.py b/bakerydemo/settings/dev.py index 4c1855a..8d81459 100644 --- a/bakerydemo/settings/dev.py +++ b/bakerydemo/settings/dev.py @@ -2,9 +2,9 @@ from .base import * # noqa: F403, F401 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 = 'http://localhost:8000' +WAGTAILADMIN_BASE_URL = "http://localhost:8000" -ALLOWED_HOSTS = ['*'] +ALLOWED_HOSTS = ["*"] diff --git a/bakerydemo/settings/production.py b/bakerydemo/settings/production.py index 22e7975..5468f3d 100644 --- a/bakerydemo/settings/production.py +++ b/bakerydemo/settings/production.py @@ -7,120 +7,132 @@ import django_cache_url 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. -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: # 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: -SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') +SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "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. # IMPORTANT: Set this to a real hostname when using this in production! # 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 = 'http://localhost:8000' +WAGTAILADMIN_BASE_URL = "http://localhost:8000" 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_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) -CACHES = {'default': django_cache_url.config()} +CACHES = {"default": django_cache_url.config()} # Configure Elasticsearch, if present in os.environ -ELASTICSEARCH_ENDPOINT = os.getenv('ELASTICSEARCH_ENDPOINT', '') +ELASTICSEARCH_ENDPOINT = os.getenv("ELASTICSEARCH_ENDPOINT", "") if ELASTICSEARCH_ENDPOINT: from elasticsearch import RequestsHttpConnection + 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: 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_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_region=AWS_REGION, - aws_service='es', + aws_service="es", ) elif AWS_REGION: # 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 # This may be useful if your credentials are obtained via EC2 instance meta data. 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_region=AWS_REGION, - aws_service='es', + aws_service="es", ) # Simplified static file serving. # 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 - INSTALLED_APPS.append('storages') + INSTALLED_APPS.append("storages") 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 - INSTALLED_APPS.append('storages') - DEFAULT_FILE_STORAGE = 'storages.backends.gcloud.GoogleCloudStorage' + INSTALLED_APPS.append("storages") + DEFAULT_FILE_STORAGE = "storages.backends.gcloud.GoogleCloudStorage" 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"), }, }, } diff --git a/bakerydemo/urls.py b/bakerydemo/urls.py index 461cf2d..63ecc2a 100644 --- a/bakerydemo/urls.py +++ b/bakerydemo/urls.py @@ -12,16 +12,13 @@ from bakerydemo.search import views as search_views from .api import api_router 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 += [ 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 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 += [ - path('', include(wagtail_urls)), + path("", include(wagtail_urls)), ] diff --git a/bakerydemo/wsgi.py b/bakerydemo/wsgi.py index 6317740..3bf310c 100644 --- a/bakerydemo/wsgi.py +++ b/bakerydemo/wsgi.py @@ -13,7 +13,7 @@ import dotenv 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")