Fix: issues #57

Closed
opened 2026-03-15 15:38:55 +00:00 by mark · 1 comment
Owner
  1. the slug needs a manual entry to work - absolutely insane
  2. I just published an article, in the Wagtail admin it had a persistent success message which took over the entire header:
    Page 'Gemini CLI: The most frustrating agent on the planet?' has been updated.
    Page 'Gemini CLI: The most frustrating agent on the planet?' has been updated.
    Page 'Gemini CLI: The most frustrating agent on the planet?' has been published. View live Edit

And it ALSO RENDERS ON THE FRONT PUBLIC FACING PAGE:
Page 'Gemini CLI: The most frustrating agent on the planet?' has been updated.

Page 'Gemini CLI: The most frustrating agent on the planet?' has been updated.

Page 'Gemini CLI: The most frustrating agent on the planet?' has been published. View live Edit

It eventually goes away in the admin, but it appears to be permanently printed to the frontend????

And it CONSTANTLY says I saved stuff in another window when I'm not??

1) the slug needs a manual entry to work - absolutely insane 2) I just published an article, in the Wagtail admin it had a persistent success message which took over the entire header: Page 'Gemini CLI: The most frustrating agent on the planet?' has been updated. Page 'Gemini CLI: The most frustrating agent on the planet?' has been updated. Page 'Gemini CLI: The most frustrating agent on the planet?' has been published. [View live](https://nohypeai.net/articles/gemini-cli-the-most-frustrating-agent-on-the-planet/) [Edit](https://nohypeai.net/cms/pages/12/edit/) And it ALSO RENDERS ON THE FRONT PUBLIC FACING PAGE: Page 'Gemini CLI: The most frustrating agent on the planet?' has been updated. Page 'Gemini CLI: The most frustrating agent on the planet?' has been updated. Page 'Gemini CLI: The most frustrating agent on the planet?' has been published. [View live](https://nohypeai.net/articles/gemini-cli-the-most-frustrating-agent-on-the-planet/) [Edit](https://nohypeai.net/cms/pages/12/edit/) It eventually goes away in the admin, but it appears to be permanently printed to the frontend???? And it CONSTANTLY says I saved stuff in another window when I'm not??
Member

Investigation Findings

Investigated all three issues. Here's the root cause analysis and proposed fix for each.


1. Slug requires manual entry

Root cause: The ArticlePageAdminForm.clean() method calls super().clean() (Wagtail's own WagtailAdminPageForm.clean()) before the custom auto-slug logic runs. Wagtail's parent clean() runs its own slug validation/sanitisation first. If the slug is empty at that point, Wagtail may add a form error or handle it in a way that conflicts with the custom auto-generation that runs afterwards.

Additionally, the slug field lives in the SEO tab (4th tab, via SeoMixin.seo_panels) while the title is in the Content tab (1st tab). Wagtail's JavaScript auto-slug generation from the title field may not sync across tabs in the TabbedInterface, so the browser-side auto-slug never fires — the user has to manually navigate to the SEO tab and type a slug.

The existing test (test_article_admin_form_clean_applies_defaults) monkeypatches super().clean() entirely, which hides this interaction.

Proposed fix: Restructure clean() so the slug (and other defaults) are populated before calling super().clean(). This ensures Wagtail's validation sees a populated slug. For example, override clean_slug() or inject defaults into self.data/cleaned_data before the parent runs. Also consider moving the slug field to the Metadata tab so it's more discoverable.

File: apps/blog/models.pyArticlePageAdminForm.clean() (line 224)


2. Admin messages rendering on the public frontend

Root cause: templates/base.html lines 29–35 render all Django messages framework messages on the public-facing frontend:

{% if messages %}
  <section aria-label="Messages" class="max-w-7xl mx-auto px-6 py-2">
    {% for message in messages %}
      <p class="...">{{ message }}</p>
    {% endfor %}
  </section>
{% endif %}

The django.contrib.messages context processor is active (in config/settings/base.py line 87), making messages available in every template. Wagtail admin operations (save, publish) add success messages to the session. The flow is:

  1. Admin saves/publishes a page in Wagtail → messages added to session
  2. Admin clicks "View live" or navigates to the public site
  3. base.html renders the messages block → admin messages appear on the public page

Since the session cookie is shared between /cms/ and the public site (same domain), admin messages leak to the frontend. This only affects the admin user's own browser session, not other visitors — but it's still wrong and alarming.

Proposed fix: Remove the {% if messages %} block from templates/base.html entirely. Wagtail's admin templates have their own message rendering. If frontend flash messages are needed later (e.g. for newsletter signup confirmation), use a separate mechanism with message tags to filter admin vs. frontend messages.

File: templates/base.html lines 29–35


3. False "saved in another window" warnings

Root cause: The ArticlePage.save() method (line 367) unconditionally mutates fields on every save:

  • Always recalculates read_time_mins (line 377)
  • May auto-generate summary if empty (line 373–374)
  • May set published_date from first_published_at (line 375–376)

This same auto-generation logic also exists in ArticlePageAdminForm.clean() (lines 228–238), creating a dual-write pattern where fields can be modified at two different points.

In Wagtail 7, the publish workflow involves multiple save operations (save draft → publish). Each save() call recalculates read_time_mins and potentially modifies other fields, creating new revisions. Wagtail's edit conflict detection compares the revision loaded in the editor with the current revision — if they differ (because the publish workflow's intermediate save created a new one), it shows the "saved in another window" warning.

Proposed fix:

  • Remove the duplicate auto-generation from save() for fields already handled by clean() (summary, category defaults). The form is the right place for these.
  • Guard read_time_mins with a change check (only update if the body actually changed).
  • Keep published_date auto-set in save() since it depends on first_published_at which is set by Wagtail during publish, but guard it to only run once.

File: apps/blog/models.pyArticlePage.save() (line 367)


Summary

Issue Root cause Fix location
Slug needs manual entry clean() auto-fills slug after super().clean() validates it; JS auto-slug broken across tabs ArticlePageAdminForm.clean()
Admin messages on frontend base.html renders all Django messages including Wagtail admin ones templates/base.html lines 29–35
"Saved in another window" save() mutates fields on every save, causing revision drift during publish workflow ArticlePage.save()

I can start on the fix branch if you want.

## Investigation Findings Investigated all three issues. Here's the root cause analysis and proposed fix for each. --- ### 1. Slug requires manual entry **Root cause:** The `ArticlePageAdminForm.clean()` method calls `super().clean()` (Wagtail's own `WagtailAdminPageForm.clean()`) **before** the custom auto-slug logic runs. Wagtail's parent `clean()` runs its own slug validation/sanitisation first. If the slug is empty at that point, Wagtail may add a form error or handle it in a way that conflicts with the custom auto-generation that runs afterwards. Additionally, the slug field lives in the **SEO tab** (4th tab, via `SeoMixin.seo_panels`) while the title is in the **Content tab** (1st tab). Wagtail's JavaScript auto-slug generation from the title field may not sync across tabs in the `TabbedInterface`, so the browser-side auto-slug never fires — the user has to manually navigate to the SEO tab and type a slug. The existing test (`test_article_admin_form_clean_applies_defaults`) monkeypatches `super().clean()` entirely, which hides this interaction. **Proposed fix:** Restructure `clean()` so the slug (and other defaults) are populated **before** calling `super().clean()`. This ensures Wagtail's validation sees a populated slug. For example, override `clean_slug()` or inject defaults into `self.data`/`cleaned_data` before the parent runs. Also consider moving the slug field to the Metadata tab so it's more discoverable. **File:** `apps/blog/models.py` — `ArticlePageAdminForm.clean()` (line 224) --- ### 2. Admin messages rendering on the public frontend **Root cause:** `templates/base.html` lines 29–35 render **all** Django messages framework messages on the public-facing frontend: ```html {% if messages %} <section aria-label="Messages" class="max-w-7xl mx-auto px-6 py-2"> {% for message in messages %} <p class="...">{{ message }}</p> {% endfor %} </section> {% endif %} ``` The `django.contrib.messages` context processor is active (in `config/settings/base.py` line 87), making messages available in every template. Wagtail admin operations (save, publish) add success messages to the session. The flow is: 1. Admin saves/publishes a page in Wagtail → messages added to session 2. Admin clicks "View live" or navigates to the public site 3. `base.html` renders the messages block → admin messages appear on the public page Since the session cookie is shared between `/cms/` and the public site (same domain), admin messages leak to the frontend. This only affects the admin user's own browser session, not other visitors — but it's still wrong and alarming. **Proposed fix:** Remove the `{% if messages %}` block from `templates/base.html` entirely. Wagtail's admin templates have their own message rendering. If frontend flash messages are needed later (e.g. for newsletter signup confirmation), use a separate mechanism with message tags to filter admin vs. frontend messages. **File:** `templates/base.html` lines 29–35 --- ### 3. False "saved in another window" warnings **Root cause:** The `ArticlePage.save()` method (line 367) **unconditionally mutates fields on every save**: - Always recalculates `read_time_mins` (line 377) - May auto-generate `summary` if empty (line 373–374) - May set `published_date` from `first_published_at` (line 375–376) This same auto-generation logic also exists in `ArticlePageAdminForm.clean()` (lines 228–238), creating a **dual-write pattern** where fields can be modified at two different points. In Wagtail 7, the publish workflow involves multiple save operations (save draft → publish). Each `save()` call recalculates `read_time_mins` and potentially modifies other fields, creating new revisions. Wagtail's edit conflict detection compares the revision loaded in the editor with the current revision — if they differ (because the publish workflow's intermediate save created a new one), it shows the "saved in another window" warning. **Proposed fix:** - Remove the duplicate auto-generation from `save()` for fields already handled by `clean()` (summary, category defaults). The form is the right place for these. - Guard `read_time_mins` with a change check (only update if the body actually changed). - Keep `published_date` auto-set in `save()` since it depends on `first_published_at` which is set by Wagtail during publish, but guard it to only run once. **File:** `apps/blog/models.py` — `ArticlePage.save()` (line 367) --- ## Summary | Issue | Root cause | Fix location | |-------|-----------|--------------| | Slug needs manual entry | `clean()` auto-fills slug **after** `super().clean()` validates it; JS auto-slug broken across tabs | `ArticlePageAdminForm.clean()` | | Admin messages on frontend | `base.html` renders all Django messages including Wagtail admin ones | `templates/base.html` lines 29–35 | | "Saved in another window" | `save()` mutates fields on every save, causing revision drift during publish workflow | `ArticlePage.save()` | I can start on the fix branch if you want.
mark closed this issue 2026-03-15 17:09:45 +00:00
Sign in to join this conversation.
No Label
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: nohype/main-site#57