Compare commits

..

3 commits

8 changed files with 309 additions and 18 deletions

View file

@ -1,5 +1,5 @@
.PHONY: help build publish
VERSION = 1.9.3
VERSION = 1.9.6
help:
@perl -nle'print $& if m{^[a-zA-Z_-]+:.*?## .*$$}' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'

View file

@ -0,0 +1,218 @@
# Generated by Django 5.1.6 on 2025-05-06 17:00
import django.db.models.deletion
from django.db import migrations, models
from home.models import HomePage
STRUCT_ORG_FIELDS = [
"struct_org_type",
"struct_org_name",
"struct_org_logo_id",
"struct_org_image_id",
"struct_org_phone",
"struct_org_address_street",
"struct_org_address_locality",
"struct_org_address_region",
"struct_org_address_postal",
"struct_org_address_country",
"struct_org_geo_lat",
"struct_org_geo_lng",
"struct_org_hours",
"struct_org_actions",
"struct_org_extra_json", ]
# put here every model names of yours that could have been filled with structured seo data;
# order will matter when searching for pages data
SEO_MODELS = [HomePage]
def fill_settings_from_pages_struct_org(apps, schema_editor):
"""
Search for pages where seo struct info was filled and use that to
fill new settings struct data
"""
SeoSettings = apps.get_model("wagtailseo", "SeoSettings")
Site = apps.get_model("wagtailcore", "Site")
for site in Site.objects.all().select_related("root_page"):
for model_name in SEO_MODELS:
model = apps.get_model("home", model_name)
page = model.objects.filter(
path__startswith=site.root_page.path,
depth__gte=site.root_page.depth
).order_by(
'path'
).exclude(struct_org_name__exact="").first()
# if you are sure that only root pages were used to fill structured data,
# you can directly use:
# page = site.root_page.specific if site.root_page.specific._meta.model_name in SEO_MODELS else None
if page is not None:
seo_settings, _ = SeoSettings.objects.get_or_create(site=site)
for field in STRUCT_ORG_FIELDS:
setattr(seo_settings, field, getattr(page, field))
seo_settings.save()
break
def fill_pages_from_settings_struct_org(apps, schema_editor):
"""
The reverse migration.
For every site, find the most top-level page inheriting from SeoMixin
and fill its struct information using the site's settings
"""
SeoSettings = apps.get_model("wagtailseo", "SeoSettings")
for seo_settings in SeoSettings.objects.all().select_related("site", "site__root_page"):
for model_name in SEO_MODELS:
model = apps.get_model("home", model_name)
page = model.objects.filter(
path__startswith=seo_settings.site.root_page.path,
depth__gte=seo_settings.site.root_page.depth
).order_by('path').first()
if page is not None:
for field in STRUCT_ORG_FIELDS:
setattr(page, field, getattr(seo_settings, field))
page.save()
break
class Migration(migrations.Migration):
dependencies = [
('blog', '0014_alter_blogpage_body'),
('wagtailimages', '0027_image_description'),
("wagtailseo", "0003_seosettings_struct_org_fields"),
]
operations = [
migrations.RemoveField(
model_name='blogindexpage',
name='struct_org_actions',
),
migrations.RemoveField(
model_name='blogindexpage',
name='struct_org_address_country',
),
migrations.RemoveField(
model_name='blogindexpage',
name='struct_org_address_locality',
),
migrations.RemoveField(
model_name='blogindexpage',
name='struct_org_address_postal',
),
migrations.RemoveField(
model_name='blogindexpage',
name='struct_org_address_region',
),
migrations.RemoveField(
model_name='blogindexpage',
name='struct_org_address_street',
),
migrations.RemoveField(
model_name='blogindexpage',
name='struct_org_extra_json',
),
migrations.RemoveField(
model_name='blogindexpage',
name='struct_org_geo_lat',
),
migrations.RemoveField(
model_name='blogindexpage',
name='struct_org_geo_lng',
),
migrations.RemoveField(
model_name='blogindexpage',
name='struct_org_hours',
),
migrations.RemoveField(
model_name='blogindexpage',
name='struct_org_image',
),
migrations.RemoveField(
model_name='blogindexpage',
name='struct_org_logo',
),
migrations.RemoveField(
model_name='blogindexpage',
name='struct_org_name',
),
migrations.RemoveField(
model_name='blogindexpage',
name='struct_org_phone',
),
migrations.RemoveField(
model_name='blogindexpage',
name='struct_org_type',
),
migrations.RemoveField(
model_name='blogpage',
name='struct_org_actions',
),
migrations.RemoveField(
model_name='blogpage',
name='struct_org_address_country',
),
migrations.RemoveField(
model_name='blogpage',
name='struct_org_address_locality',
),
migrations.RemoveField(
model_name='blogpage',
name='struct_org_address_postal',
),
migrations.RemoveField(
model_name='blogpage',
name='struct_org_address_region',
),
migrations.RemoveField(
model_name='blogpage',
name='struct_org_address_street',
),
migrations.RemoveField(
model_name='blogpage',
name='struct_org_extra_json',
),
migrations.RemoveField(
model_name='blogpage',
name='struct_org_geo_lat',
),
migrations.RemoveField(
model_name='blogpage',
name='struct_org_geo_lng',
),
migrations.RemoveField(
model_name='blogpage',
name='struct_org_hours',
),
migrations.RemoveField(
model_name='blogpage',
name='struct_org_image',
),
migrations.RemoveField(
model_name='blogpage',
name='struct_org_logo',
),
migrations.RemoveField(
model_name='blogpage',
name='struct_org_name',
),
migrations.RemoveField(
model_name='blogpage',
name='struct_org_phone',
),
migrations.RemoveField(
model_name='blogpage',
name='struct_org_type',
),
migrations.AlterField(
model_name='blogindexpage',
name='og_image',
field=models.ForeignKey(blank=True, help_text='Shown when linking to this page on social media. If blank, may show an image from the page, or the default from Settings > SEO.', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailimages.image', verbose_name='Preview image'),
),
migrations.AlterField(
model_name='blogpage',
name='og_image',
field=models.ForeignKey(blank=True, help_text='Shown when linking to this page on social media. If blank, may show an image from the page, or the default from Settings > SEO.', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailimages.image', verbose_name='Preview image'),
),
]

View file

@ -54,12 +54,12 @@
{% with tags=page.tags.all %}
{% if tags %}
<div class="flex items-center gap-x-4 text-xs my-6">
<div class="flex items-center justify-center gap-x-4 text-xs my-6">
<div class="tags">
<h2 class="sr-only">Tags</h2>
<ul class="flex">
{% for tag in tags %}
<li class="space-x-2"><span class="emoji">🏷</span>
<li><span class="emoji">🏷</span>
<a class="pr-2" href="{% slugurl 'tags' %}?tag={{ tag }}">{{ tag }}</a>
</li>
{% endfor %}
@ -79,8 +79,4 @@
</nav>
</section>
<section>
{% include 'newsletter/snippets/signup_form.html' %}
</section>
{% endblock %}

View file

@ -0,0 +1,80 @@
# Generated by Django 5.1.6 on 2025-05-06 17:00
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('home', '0006_alter_homepage_body'),
('wagtailimages', '0027_image_description'),
]
operations = [
migrations.RemoveField(
model_name='homepage',
name='struct_org_actions',
),
migrations.RemoveField(
model_name='homepage',
name='struct_org_address_country',
),
migrations.RemoveField(
model_name='homepage',
name='struct_org_address_locality',
),
migrations.RemoveField(
model_name='homepage',
name='struct_org_address_postal',
),
migrations.RemoveField(
model_name='homepage',
name='struct_org_address_region',
),
migrations.RemoveField(
model_name='homepage',
name='struct_org_address_street',
),
migrations.RemoveField(
model_name='homepage',
name='struct_org_extra_json',
),
migrations.RemoveField(
model_name='homepage',
name='struct_org_geo_lat',
),
migrations.RemoveField(
model_name='homepage',
name='struct_org_geo_lng',
),
migrations.RemoveField(
model_name='homepage',
name='struct_org_hours',
),
migrations.RemoveField(
model_name='homepage',
name='struct_org_image',
),
migrations.RemoveField(
model_name='homepage',
name='struct_org_logo',
),
migrations.RemoveField(
model_name='homepage',
name='struct_org_name',
),
migrations.RemoveField(
model_name='homepage',
name='struct_org_phone',
),
migrations.RemoveField(
model_name='homepage',
name='struct_org_type',
),
migrations.AlterField(
model_name='homepage',
name='og_image',
field=models.ForeignKey(blank=True, help_text='Shown when linking to this page on social media. If blank, may show an image from the page, or the default from Settings > SEO.', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailimages.image', verbose_name='Preview image'),
),
]

View file

@ -82,9 +82,4 @@
</div>
</section>
<section>
<h2 id="newsletter" class="sr-only">Newsletter</h2>
{% include 'newsletter/snippets/signup_form.html' %}
</section>
{% endblock content %}

View file

@ -4,6 +4,7 @@
<html lang="en" class="h-full antialiased">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width">
<meta name="fediverse:creator" content="@iamkonstantin@mastodon.social" />
{% include "wagtailseo/meta.html" %}
<title>
@ -80,5 +81,6 @@
{# Override this in templates to add extra javascript #}
{% endblock %}
{% include "wagtailseo/struct_data.html" %}
{% include "wagtailseo/struct_org_data.html" %}
</body>
</html>

View file

@ -1,8 +1,8 @@
Django>=5.1.4,<5.2
wagtail>=6.4.1,<6.5
Django>=5.1,<5.3
wagtail>=6.4,<7.1
whitenoise>=6.6,<7.0
wagtailcodeblock>=1.29.0.2,<2.0
django-tailwind>=3.6.0
django-browser-reload>=1.17
Wand==0.6.13
wagtail-seo==2.5.0
wagtail-seo==3.0.0

View file

@ -124,11 +124,11 @@
}
.tags ul {
@apply flex space-x-4 text-center text-sm;
@apply flex-col sm:flex-row sm:space-x-2 text-center text-sm;
}
.tags li {
@apply p-4 inline-flex items-center rounded-2xl bg-green-50 px-2 py-1 font-medium text-green-700 ring-1 ring-inset ring-green-600/20;
@apply p-3 inline-flex items-center rounded-2xl px-2 py-1 text-sm text-black dark:text-white ring-1 ring-inset ring-orange-700/20 dark:ring-white bg-orange-50 dark:bg-transparent;
}
.tags ul li::before {
@ -137,7 +137,7 @@
}
.tags a {
@apply border-b-0 w-full;
@apply border-b-0 w-full m-0;
}
.blog-pages a {