Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[7434] - FE/BE Structured data field for Mozfest pages #7568

Merged
merged 26 commits into from
Jan 26, 2022
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
b75fee6
Add structured data field to mozefest pages
stevedya Oct 5, 2021
5ec54d6
Merge branch 'main' into feature/7536-7535-structured-data
stevedya Oct 14, 2021
4bec8f2
Update migrations
Oct 15, 2021
9ee28fd
Merge branch 'main' into feature/7536-7535-structured-data
Oct 19, 2021
0f17204
Try commenting out an old migration task that likely has already been
Oct 19, 2021
6fbbdb4
Fix flake issues, update migrations
Oct 19, 2021
ffb815e
Merge branch 'main' into feature/7536-7535-structured-data
Oct 21, 2021
fad1be5
[7434] fix merge conflict from main branch
Dec 7, 2021
2528770
[7434] rename migration
Dec 7, 2021
c2d47d6
[7434] uncomment migration action
Dec 7, 2021
c909a41
[7434] fix wide image migration
Dec 7, 2021
8d4051f
[7434] fix wide image migration
Dec 7, 2021
c61d0b2
Merge branch 'main' into feature/7536-7535-structured-data
richbrennan Dec 8, 2021
c1aee37
Merge branch 'main' into feature/7536-7535-structured-data
richbrennan Dec 9, 2021
990d60b
[7434] remove structured data character limit
Dec 9, 2021
fdf620d
Merge branch 'main' into feature/7536-7535-structured-data
richbrennan Dec 13, 2021
99230c3
[7536] generalise tag for json data
Dec 13, 2021
0504981
Revert "[7536] generalise tag for json data"
Dec 13, 2021
979cd95
Merge branch 'main' into feature/7536-7535-structured-data
richbrennan Dec 13, 2021
00865f6
Merge branch 'main' into feature/7536-7535-structured-data
richbrennan Dec 14, 2021
ac8af7c
[7434] update migration following main merge
Dec 14, 2021
fa38a60
Merge branch 'main' into feature/7536-7535-structured-data
richbrennan Dec 16, 2021
de7502a
[7434] recreate migration
Dec 16, 2021
8f0eaab
Merge branch 'main' into feature/7536-7535-structured-data
Pomax Jan 24, 2022
4c3219f
migration fix
Pomax Jan 25, 2022
33f1f5b
Merge branch 'main' into feature/7536-7535-structured-data
Pomax Jan 25, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class Migration(migrations.Migration):
field=wagtail.core.fields.StreamField([('paragraph', wagtail.core.blocks.RichTextBlock(features=['bold', 'italic', 'large', 'h2', 'h3', 'h4', 'h5', 'ol', 'ul', 'link', 'hr'])), ('card_grid', wagtail.core.blocks.StructBlock([('cards', wagtail.core.blocks.ListBlock(wagtail.core.blocks.StructBlock([('image', wagtail.images.blocks.ImageChooserBlock()), ('alt_text', wagtail.core.blocks.CharBlock(help_text="Alt text for card's image.", required=False)), ('title', wagtail.core.blocks.CharBlock(help_text='Heading for the card.')), ('body', wagtail.core.blocks.TextBlock(help_text='Body text of the card.')), ('link_url', wagtail.core.blocks.CharBlock(help_text='URL that this card should link out to.')), ('link_label', wagtail.core.blocks.CharBlock(help_text='Label for the URL link above.'))]), help_text='Please use a minimum of 2 cards.'))])), ('image', wagtail.core.blocks.StructBlock([('image', wagtail.images.blocks.ImageChooserBlock()), ('altText', wagtail.core.blocks.CharBlock(help_text='Image description (for screen readers).', required=True)), ('caption', wagtail.core.blocks.CharBlock(required=False)), ('captionURL', wagtail.core.blocks.CharBlock(help_text='Optional URL that this caption should link out to.', required=False)), ('wide_image', wagtail.core.blocks.BooleanBlock(default=False, help_text='Would you like to use a wider image on desktop?', required=False)), ('image_width', wagtail.core.blocks.ChoiceBlock(choices=[('normal', 'Normal'), ('wide', 'Wide'), ('full_width', 'Full Width')], help_text='Wide images are col-12, Full-Width Images reach both ends of the screen (16:6 images recommended for full width)'))])), ('image_text', wagtail.core.blocks.StructBlock([('image', wagtail.images.blocks.ImageChooserBlock()), ('altText', wagtail.core.blocks.CharBlock(help_text='Image description (for screen readers).', required=True)), ('text', wagtail.core.blocks.RichTextBlock(features=['bold', 'italic', 'h2', 'h3', 'h4', 'h5', 'h6', 'ol', 'ul', 'link'])), ('url', wagtail.core.blocks.CharBlock(help_text='Optional URL that this image should link out to.', required=False)), ('top_divider', wagtail.core.blocks.BooleanBlock(help_text='Optional divider above content block.', required=False)), ('bottom_divider', wagtail.core.blocks.BooleanBlock(help_text='Optional divider below content block.', required=False))])), ('image_text_mini', wagtail.core.blocks.StructBlock([('image', wagtail.images.blocks.ImageChooserBlock()), ('altText', wagtail.core.blocks.CharBlock(help_text='Image description (for screen readers).', required=True)), ('text', wagtail.core.blocks.RichTextBlock(features=['bold', 'italic', 'link']))])), ('image_grid', wagtail.core.blocks.StructBlock([('grid_items', wagtail.core.blocks.ListBlock(wagtail.core.blocks.StructBlock([('image', wagtail.images.blocks.ImageChooserBlock()), ('alt_text', wagtail.core.blocks.CharBlock(help_text='Alt text for this image.', required=False)), ('caption', wagtail.core.blocks.CharBlock(help_text='Please remember to properly attribute any images we use.', required=False)), ('url', wagtail.core.blocks.CharBlock(help_text='Optional URL that this figure should link out to.', required=False)), ('square_image', wagtail.core.blocks.BooleanBlock(default=True, help_text='If left checked, the image will be cropped to be square.', required=False))])))])), ('video', wagtail.core.blocks.StructBlock([('url', wagtail.core.blocks.CharBlock(help_text='For YouTube: go to your YouTube video and click “Share,” then “Embed,” and then copy and paste the provided URL only. For example: https://www.youtube.com/embed/3FIVXBawyQw For Vimeo: follow similar steps to grab the embed URL. For example: https://player.vimeo.com/video/9004979')), ('caption', wagtail.core.blocks.CharBlock(required=False)), ('captionURL', wagtail.core.blocks.CharBlock(help_text='Optional URL for caption to link to.', required=False)), ('video_width', wagtail.core.blocks.ChoiceBlock(choices=[('normal', 'Normal'), ('wide', 'Wide'), ('full_width', 'Full Width')], help_text='Wide videos are col-12, Full-Width videos reach both ends of the screen.'))])), ('iframe', wagtail.core.blocks.StructBlock([('url', wagtail.core.blocks.CharBlock(help_text='Please note that only URLs from white-listed domains will work.')), ('height', wagtail.core.blocks.IntegerBlock(help_text='Optional integer pixel value for custom iFrame height', required=False)), ('caption', wagtail.core.blocks.CharBlock(required=False)), ('captionURL', wagtail.core.blocks.CharBlock(help_text='Optional URL that this caption should link out to.', required=False)), ('iframe_width', wagtail.core.blocks.ChoiceBlock(choices=[('normal', 'Normal'), ('wide', 'Wide'), ('full_width', 'Full Width')], help_text='Wide iframes are col-12, Full-Width iframes reach both ends of the screen'))])), ('linkbutton', wagtail.core.blocks.StructBlock([('label', wagtail.core.blocks.CharBlock()), ('URL', wagtail.core.blocks.CharBlock()), ('styling', wagtail.core.blocks.ChoiceBlock(choices=[('btn-primary', 'Primary button'), ('btn-secondary', 'Secondary button')]))])), ('spacer', wagtail.core.blocks.StructBlock([('size', wagtail.core.blocks.ChoiceBlock(choices=[('1', 'quarter spacing'), ('2', 'half spacing'), ('3', 'single spacing'), ('4', 'one and a half spacing'), ('5', 'triple spacing')]))])), ('quote', wagtail.core.blocks.StructBlock([('quotes', wagtail.core.blocks.ListBlock(wagtail.core.blocks.StructBlock([('quote', wagtail.core.blocks.CharBlock()), ('attribution', wagtail.core.blocks.CharBlock(required=False))])))])), ('pulse_listing', wagtail.core.blocks.StructBlock([('search_terms', wagtail.core.blocks.CharBlock(help_text='Test your search at mozillapulse.org/search', label='Search', required=False)), ('max_number_of_results', wagtail.core.blocks.IntegerBlock(default=6, help_text='Choose 1-12. If you want visitors to see more, link to a search or tag on Pulse.', max_value=12, min_value=0, required=True)), ('only_featured_entries', wagtail.core.blocks.BooleanBlock(default=False, help_text='Featured items are selected by Pulse moderators.', label='Display only featured entries', required=False)), ('newest_first', wagtail.core.blocks.ChoiceBlock(choices=[('True', 'Show newer entries first'), ('False', 'Show older entries first')], label='Sort')), ('advanced_filter_header', wagtail.core.blocks.static_block.StaticBlock(admin_text='-------- ADVANCED FILTERS: OPTIONS TO DISPLAY FEWER, MORE TARGETED RESULTS. --------', label=' ')), ('issues', wagtail.core.blocks.ChoiceBlock(choices=[('all', 'All'), ('Decentralization', 'Decentralization'), ('Digital Inclusion', 'Digital Inclusion'), ('Online Privacy & Security', 'Online Privacy & Security'), ('Open Innovation', 'Open Innovation'), ('Web Literacy', 'Web Literacy')])), ('help', wagtail.core.blocks.ChoiceBlock(choices=[('all', 'All'), ('Attend', 'Attend'), ('Create content', 'Create content'), ('Code', 'Code'), ('Design', 'Design'), ('Fundraise', 'Fundraise'), ('Join community', 'Join community'), ('Localize & translate', 'Localize & translate'), ('Mentor', 'Mentor'), ('Plan & organize', 'Plan & organize'), ('Promote', 'Promote'), ('Take action', 'Take action'), ('Test & feedback', 'Test & feedback'), ('Write documentation', 'Write documentation')], label='Type of help needed')), ('direct_link', wagtail.core.blocks.BooleanBlock(default=False, help_text='Checked: user goes to project link. Unchecked: user goes to pulse entry', label='Direct link', required=False))])), ('profile_listing', wagtail.core.blocks.StructBlock([('max_number_of_results', wagtail.core.blocks.IntegerBlock(default=12, help_text='Pick up to 48 profiles.', max_value=48, min_value=1, required=True)), ('advanced_filter_header', wagtail.core.blocks.static_block.StaticBlock(admin_text='-------- ADVANCED FILTERS: OPTIONS TO DISPLAY FEWER, MORE TARGETED RESULTS. --------', label=' ')), ('profile_type', wagtail.core.blocks.CharBlock(default='', help_text='Example: Fellow.', required=False)), ('program_type', wagtail.core.blocks.CharBlock(default='', help_text='Example: Tech Policy.', required=False)), ('year', wagtail.core.blocks.CharBlock(default='', required=False))])), ('profile_by_id', wagtail.core.blocks.StructBlock([('ids', wagtail.core.blocks.CharBlock(help_text='Show profiles for pulse users with specific profile ids (mozillapulse.org/profile/[##]). For multiple profiles, specify a comma separated list (e.g. 85,105,332).', label='Profile by ID'))])), ('profile_directory', wagtail.core.blocks.StructBlock([('max_number_of_results', wagtail.core.blocks.IntegerBlock(default=12, help_text='Pick up to 48 profiles.', max_value=48, min_value=1, required=True)), ('advanced_filter_header', wagtail.core.blocks.static_block.StaticBlock(admin_text='-------- ADVANCED FILTERS: OPTIONS TO DISPLAY FEWER, MORE TARGETED RESULTS. --------', label=' ')), ('profile_type', wagtail.core.blocks.CharBlock(default='', help_text='Example: Fellow.', required=False)), ('program_type', wagtail.core.blocks.CharBlock(default='', help_text='Example: Tech Policy.', required=False)), ('year', wagtail.core.blocks.CharBlock(default='', required=False)), ('filter_values', wagtail.core.blocks.CharBlock(default='2019,2018,2017,2016,2015,2014,2013', help_text='Example: 2019,2018,2017,2016,2015,2014,2013', required=True))])), ('recent_blog_entries', wagtail.core.blocks.StructBlock([('title', wagtail.core.blocks.CharBlock(required=False)), ('tag_filter', wagtail.core.blocks.CharBlock(help_text='Test this filter at foundation.mozilla.org/blog/tags/', label='Filter by Tag', required=False)), ('category_filter', wagtail.core.blocks.ChoiceBlock(choices=networkapi.wagtailpages.pagemodels.blog.blog_category.BlogPageCategory.get_categories, help_text='Test this filter at foundation.mozilla.org/blog/category/', label='Filter by Category', required=False)), ('top_divider', wagtail.core.blocks.BooleanBlock(help_text='Optional divider above content block.', required=False)), ('bottom_divider', wagtail.core.blocks.BooleanBlock(help_text='Optional divider below content block.', required=False))])), ('blog_set', wagtail.core.blocks.StructBlock([('title', wagtail.core.blocks.CharBlock()), ('top_divider', wagtail.core.blocks.BooleanBlock(help_text='Optional divider above content block.', required=False)), ('bottom_divider', wagtail.core.blocks.BooleanBlock(help_text='Optional divider below content block.', required=False)), ('blog_pages', wagtail.core.blocks.ListBlock(wagtail.core.blocks.PageChooserBlock(page_type=['wagtailpages.BlogPage'])))])), ('airtable', wagtail.core.blocks.StructBlock([('url', wagtail.core.blocks.URLBlock(help_text="Copied from the Airtable embed code. The word 'embed' will be in the url")), ('height', wagtail.core.blocks.IntegerBlock(default=533, help_text='The pixel height on desktop view, usually copied from the Airtable embed code'))])), ('typeform', wagtail.core.blocks.StructBlock([('embed_id', wagtail.core.blocks.CharBlock(help_text='The embed id of your Typeform page (e.g. if the form is on admin.typeform.com/form/e8zScc6t, the id will be: e8zScc6t)', required=True)), ('button_type', wagtail.core.blocks.ChoiceBlock(choices=[('btn-primary', 'Primary button'), ('btn-secondary', 'Secondary button')])), ('button_text', wagtail.core.blocks.CharBlock(help_text='This is a text prompt for users to open the typeform content', required=True))]))]),
),
# Updating "image_width" of any image with "wide" set to True.
migrations.RunPython(loop_through_pages_with_image_blocks),
# migrations.RunPython(loop_through_pages_with_image_blocks),
Copy link
Collaborator

@b-ggs b-ggs Oct 21, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've commented out this function because it was causing issues in the CI.

Specifically this line was attempting to access the structured_data field when it doesn't exist at the time of migration and throws django.db.utils.ProgrammingError: column mozfest_mozfestprimarypage.structured_data does not exist:

https://github.com/mozilla/foundation.mozilla.org/blob/ffb815e07d195664db5d9bb96023359456f9e3fd/network-api/networkapi/mozfest/migrations/0017_update_wide_images.py#L15

This is an example of the failed CI run: https://github.com/mozilla/foundation.mozilla.org/runs/3937484149?check_suite_focus=true#step:9:453

In case the log is unavailable at the time of review, here's a summary of the run:

CI Summary

Wagtail CI

Preroll

  python network-api/manage.py migrate --no-input

Running migrations:

[...]

  Applying mozfest.0016_auto_20210525_1516... OK
Traceback (most recent call last):
  File "/opt/hostedtoolcache/Python/3.8.12/x64/lib/python3.8/site-packages/django/db/backends/utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
psycopg2.errors.UndefinedColumn: column mozfest_mozfestprimarypage.structured_data does not exist
LINE 1: ..."mozfest_mozfestprimarypage"."use_wide_template", "mozfest_m...
                                                             ^


The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "network-api/manage.py", line 34, in <module>
    execute_from_command_line(sys.argv)
  File "/opt/hostedtoolcache/Python/3.8.12/x64/lib/python3.8/site-packages/django/core/management/__init__.py", line 401, in execute_from_command_line
    utility.execute()
  File "/opt/hostedtoolcache/Python/3.8.12/x64/lib/python3.8/site-packages/django/core/management/__init__.py", line 395, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/opt/hostedtoolcache/Python/3.8.12/x64/lib/python3.8/site-packages/django/core/management/base.py", line 330, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/opt/hostedtoolcache/Python/3.8.12/x64/lib/python3.8/site-packages/django/core/management/base.py", line 371, in execute
    output = self.handle(*args, **options)
  File "/opt/hostedtoolcache/Python/3.8.12/x64/lib/python3.8/site-packages/django/core/management/base.py", line 85, in wrapped
    res = handle_func(*args, **kwargs)
  File "/opt/hostedtoolcache/Python/3.8.12/x64/lib/python3.8/site-packages/django/core/management/commands/migrate.py", line 243, in handle
    post_migrate_state = executor.migrate(
  File "/opt/hostedtoolcache/Python/3.8.12/x64/lib/python3.8/site-packages/django/db/migrations/executor.py", line 117, in migrate
    state = self._migrate_all_forwards(state, plan, full_plan, fake=fake, fake_initial=fake_initial)
  File "/opt/hostedtoolcache/Python/3.8.12/x64/lib/python3.8/site-packages/django/db/migrations/executor.py", line 147, in _migrate_all_forwards
    state = self.apply_migration(state, migration, fake=fake, fake_initial=fake_initial)
  File "/opt/hostedtoolcache/Python/3.8.12/x64/lib/python3.8/site-packages/django/db/migrations/executor.py", line 227, in apply_migration
    state = migration.apply(state, schema_editor)
  File "/opt/hostedtoolcache/Python/3.8.12/x64/lib/python3.8/site-packages/django/db/migrations/migration.py", line 124, in apply
    operation.database_forwards(self.app_label, schema_editor, old_state, project_state)
  File "/opt/hostedtoolcache/Python/3.8.12/x64/lib/python3.8/site-packages/django/db/migrations/operations/special.py", line 190, in database_forwards
    self.code(from_state.apps, schema_editor)
  File "/home/runner/work/foundation.mozilla.org/foundation.mozilla.org/network-api/networkapi/mozfest/migrations/0017_update_wide_images.py", line 15, in loop_through_pages_with_image_blocks
    for page in MozfestPrimaryPage.objects.all():
  File "/opt/hostedtoolcache/Python/3.8.12/x64/lib/python3.8/site-packages/django/db/models/query.py", line 287, in __iter__
    self._fetch_all()
  File "/opt/hostedtoolcache/Python/3.8.12/x64/lib/python3.8/site-packages/django/db/models/query.py", line 1308, in _fetch_all
    self._result_cache = list(self._iterable_class(self))
  File "/opt/hostedtoolcache/Python/3.8.12/x64/lib/python3.8/site-packages/django/db/models/query.py", line 53, in __iter__
    results = compiler.execute_sql(chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size)
  File "/opt/hostedtoolcache/Python/3.8.12/x64/lib/python3.8/site-packages/django/db/models/sql/compiler.py", line 1156, in execute_sql
    cursor.execute(sql, params)
  File "/opt/hostedtoolcache/Python/3.8.12/x64/lib/python3.8/site-packages/django/db/backends/utils.py", line 98, in execute
    return super().execute(sql, params)
  File "/opt/hostedtoolcache/Python/3.8.12/x64/lib/python3.8/site-packages/django/db/backends/utils.py", line 66, in execute
    return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
  File "/opt/hostedtoolcache/Python/3.8.12/x64/lib/python3.8/site-packages/django/db/backends/utils.py", line 75, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "/opt/hostedtoolcache/Python/3.8.12/x64/lib/python3.8/site-packages/django/db/backends/utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
  File "/opt/hostedtoolcache/Python/3.8.12/x64/lib/python3.8/site-packages/django/db/utils.py", line 90, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "/opt/hostedtoolcache/Python/3.8.12/x64/lib/python3.8/site-packages/django/db/backends/utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
django.db.utils.ProgrammingError: column mozfest_mozfestprimarypage.structured_data does not exist
LINE 1: ..."mozfest_mozfestprimarypage"."use_wide_template", "mozfest_m...
                                                             ^

  Applying mozfest.0017_update_wide_images...
Error: Process completed with exit code 1.

I figured it would be safe to comment out this line since this migration has likely already been done on production, but I'm not sure if you have a protocol in place for these kinds of events. Please let me know if there are alternate ways we can resolve this.

Copy link
Contributor

@Pomax Pomax Oct 21, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Migration 0017 should only ever run if it hasn't already been applied, and any models that are used in the migration functions should be "constructed" from the database schema rather than loaded from any .py file to avoid exactly this situation... looks like we forgot that for this file!

Rather than commenting out the code, let's fix how that MozfestPrimaryPage gets loaded in: rather than having a from networkapi.mozfest.models import MozfestPrimaryPage up top, the migration code that uses it should get that model from the current run state, using MozfestPrimaryPage = apps.get_model('mozfest', 'MozfestPrimaryPage') as first line in the migration function.

See, for example, https://github.com/mozilla/foundation.mozilla.org/blob/main/network-api/networkapi/mozfest/migrations/0001_to_0015.py#L14

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Pomax

I've fixed the migration that was causing the issue. It was tricky to test but I have console output of before and after running it locally. The second call to p = MozfestPrimaryPage.objects.get(id=161) is after the migration is run, note the 'image_width': 'wide' in the second p.body.raw_data output.

It won't be run on production anyway, but it does seem to work.

Note: the old wide_image field wasn't removed during my local test but is in the submitted migration.

Screenshot from 2021-12-07 16-04-26

# Removing old "Wide" boolean field
migrations.AlterField(
model_name='mozfestprimarypage',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 3.1.11 on 2021-10-19 10:21

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('mozfest', '0021_add_spaces_cards'),
]

operations = [
migrations.AddField(
model_name='mozfestprimarypage',
name='structured_data',
field=models.TextField(blank=True, help_text='Structured data JSON for Google search results. Do not include the <script> tag. See https://schema.org/ for properties and https://validator.schema.org/ to test validity.', max_length=1000, null=True),
),
]
13 changes: 13 additions & 0 deletions network-api/networkapi/mozfest/models.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from django import forms
from django.db import models
from wagtail.admin.edit_handlers import FieldPanel, StreamFieldPanel
from wagtail.core.fields import StreamField, RichTextField
Expand Down Expand Up @@ -81,6 +82,18 @@ class MozfestPrimaryPage(FoundationMetadataPageMixin, FoundationBannerInheritanc
FieldPanel('use_wide_template')
]

structured_data = models.TextField(
max_length=1000,
help_text='Structured data JSON for Google search results. Do not include the <script> tag. '
'See https://schema.org/ for properties and https://validator.schema.org/ to test validity.',
blank=True,
null=True,
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a structured schema (custom) field that we can use instead, that runs schema validation as part of its clean() or save() process? (Or, is there an off the shelf one that we can slot in for this purpose?)

Non-technical staff will have no idea what to do with those websites, and I suspect even some technical staff will be scratching their heads =)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be too late but this might work: https://pypi.org/project/wagtail-schema.org/


promote_panels = FoundationMetadataPageMixin.promote_panels + [
FieldPanel('structured_data', widget=forms.Textarea(attrs={"rows": 10}))
]

def get_template(self, request):
if self.use_wide_template:
return 'mozfest/mozfest_primary_page_wide.html'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@
{% blocktrans %}Mozilla Festival{% endblocktrans %}{% if page.specifics.seo_title %} - {{ page.specifics.seo_title }}{% else %} - {{ page.title }}{% endif %}
{% endblock %}

{% block org_schema %}
{% if page.structured_data %}
<script type="application/ld+json">
richbrennan marked this conversation as resolved.
Show resolved Hide resolved
{{ page.structured_data|safe }}
</script>
{% endif %}
{% endblock %}

{% block body_id %}mozfest-{% block mozfest_body_id %}home{% endblock %}{% endblock %}

Expand Down