Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ coverage.xml
# Django stuff:
*.log
local_settings.py
db.sqlite3
# db.sqlite3
db.sqlite3-journal

# Flask stuff:
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ Admin and frontend page response checker

## `Live` testing scenario

*If you run check_responses command on this branch it will not show any errors*

Wagtail 3 has had some extensive changes over previous verions: [Documentation](https://docs.wagtail.org/en/stable/releases/3.0.html)

Mostly, if you miss renaming an import it can be seen quite quickly when running the site. But some other changes can be hard to spot. E.G.
Expand Down
Binary file added db.sqlite3
Binary file not shown.
Empty file added home/__init__.py
Empty file.
14 changes: 14 additions & 0 deletions home/edit_handlers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from django.template.loader import render_to_string
from django.utils.safestring import mark_safe
from wagtail.admin.edit_handlers import EditHandler


class CustomHelpPanel(EditHandler):
template = "custom/help_panel.html"

def render(self):
return mark_safe(
render_to_string(
self.template, {"self": self, "title": self.form.parent_page.title}
)
)
Empty file added home/management/__init__.py
Empty file.
Empty file.
163 changes: 163 additions & 0 deletions home/management/commands/check_responses.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
import requests
from django.core.management.base import BaseCommand
from wagtail.core.models import Site


class Command(BaseCommand):
"""A command to run against a development site that is running and ready to accept requests.

Requests are mode to one single page of each page model for both
the admin site (edit) and front end (view) and it reports the response codes.

What out for page paths highlighted in `red` and investigate the error 500.

Params:

--host: the hostname and port on your local machine
--site_id: the id of the site you want run to tests against
--username: the username of an admin account
--password: the password of the admin account

Run: python manage.py check_responses
"""

help = "Check if admin response is 200 for each page content type when entering edit mode."

def add_arguments(self, parser):
parser.add_argument(
"--host",
default="http://127.0.0.1:8000",
help="The URL to check",
)
parser.add_argument(
"--site_id",
default=None,
help="The ID of the site to check",
)
parser.add_argument(
"--username",
default="admin",
help="The username to use",
)
parser.add_argument(
"--password",
default="password",
help="The password to use",
)

def handle(self, *args, **options):
with requests.Session() as session:
# Login
url = f"{options['host']}/admin/login/"

try:
session.get(url)
except requests.exceptions.ConnectionError:
self.stderr.write(
self.style.ERROR(
f"Could not connect to {options['host']}. Is the server running?"
)
)
return
except requests.exceptions.InvalidSchema:
self.stderr.write(
self.style.ERROR(
f"Could not connect to {options['host']}. Invalid schema"
)
)
return
except requests.exceptions.MissingSchema:
self.stderr.write(
self.style.ERROR(
f"Could not connect to {options['host']}. Missing schema"
)
)
return

csrftoken = session.cookies["csrftoken"]
login_data = dict(
username=options["username"],
password=options["password"],
csrfmiddlewaretoken=csrftoken,
next="/admin/",
)

logged_in = session.post(url, data=login_data).content

if "Forgotten password?" in logged_in.decode("utf-8"):
self.stderr.write(
self.style.ERROR(
f"Could not log in to {options['host']}. Is the username and password correct?"
)
)
exit()

try:
if options["site_id"]:
site = Site.objects.get(id=options["site_id"])
else:
site = Site.objects.get(is_default_site=True)
except Site.DoesNotExist:
self.stderr.write(
self.style.ERROR(
f"Could not find a site with id {options['site_id']}."
)
)
return
items = (
site.root_page.get_descendants(inclusive=True)
.defer_streamfields()
.specific()
)
track_class_names = []
result = []

for item in items:
class_name = item.__class__.__name__
if not class_name in track_class_names:
track_class_names.append(class_name)
result.append(
{
"title": item.title,
"url": f"{options['host']}{item.url}",
"id": item.id,
"editor_url": f"{options['host']}/admin/pages/{item.id}/edit/",
"class_name": class_name,
}
)

self.stdout.write(f"Checking {len(result)} content types...")
self.stdout.write("============================")
for count, content_type in enumerate(sorted(track_class_names)):
if count <= 8:
self.stdout.write(f" {count + 1}. {content_type}")
else:
self.stdout.write(f"{count + 1}. {content_type}")
self.stdout.write("============================\n")
# Check the admin url's
for page in result:
self.stdout.write(f"{page['title']} ( {page['class_name']} ) ↓\n")
response = session.get(page["editor_url"])
if response.status_code != 200:
self.stderr.write(
self.style.ERROR(
f"{page['editor_url']} ← {response.status_code}"
)
)
else:
self.stdout.write(self.style.SUCCESS(f"{page['editor_url']} ← 200"))
response = session.get(page["url"])
if response.status_code != 200:
if response.status_code == 404:
self.stderr.write(
self.style.WARNING(
f"{page['url']} ← {response.status_code} probably a draft page"
)
)
else:
self.stderr.write(
self.style.ERROR(f"{page['url']} ← {response.status_code}")
)
else:
self.stdout.write(self.style.SUCCESS(f"{page['url']} ← 200"))
self.stdout.write("-\n")
32 changes: 32 additions & 0 deletions home/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# -*- coding: utf-8 -*-
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("wagtailcore", "0040_page_draft_title"),
]

operations = [
migrations.CreateModel(
name="HomePage",
fields=[
(
"page_ptr",
models.OneToOneField(
on_delete=models.CASCADE,
parent_link=True,
auto_created=True,
primary_key=True,
serialize=False,
to="wagtailcore.Page",
),
),
],
options={
"abstract": False,
},
bases=("wagtailcore.page",),
),
]
62 changes: 62 additions & 0 deletions home/migrations/0002_create_homepage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# -*- coding: utf-8 -*-
from django.db import migrations


def create_homepage(apps, schema_editor):
# Get models
ContentType = apps.get_model("contenttypes.ContentType")
Page = apps.get_model("wagtailcore.Page")
Site = apps.get_model("wagtailcore.Site")
HomePage = apps.get_model("home.HomePage")

# Delete the default homepage
# If migration is run multiple times, it may have already been deleted
Page.objects.filter(id=2).delete()

# Create content type for homepage model
homepage_content_type, __ = ContentType.objects.get_or_create(
model="homepage", app_label="home"
)

# Create a new homepage
homepage = HomePage.objects.create(
title="Home",
draft_title="Home",
slug="home",
content_type=homepage_content_type,
path="00010001",
depth=2,
numchild=0,
url_path="/home/",
)

# Create a site with the new homepage set as the root
Site.objects.create(hostname="localhost", root_page=homepage, is_default_site=True)


def remove_homepage(apps, schema_editor):
# Get models
ContentType = apps.get_model("contenttypes.ContentType")
HomePage = apps.get_model("home.HomePage")

# Delete the default homepage
# Page and Site objects CASCADE
HomePage.objects.filter(slug="home", depth=2).delete()

# Delete content type for homepage model
ContentType.objects.filter(model="homepage", app_label="home").delete()


class Migration(migrations.Migration):

run_before = [
("wagtailcore", "0053_locale_model"),
]

dependencies = [
("home", "0001_initial"),
]

operations = [
migrations.RunPython(create_homepage, remove_homepage),
]
42 changes: 42 additions & 0 deletions home/migrations/0003_standardpage_homepage_body.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Generated by Django 4.0.7 on 2022-10-03 20:39

import django.db.models.deletion
import wagtail.core.fields
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("wagtailcore", "0066_collection_management_permissions"),
("home", "0002_create_homepage"),
]

operations = [
migrations.CreateModel(
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",
),
),
("body", wagtail.core.fields.RichTextField(blank=True)),
],
options={
"abstract": False,
},
bases=("wagtailcore.page",),
),
migrations.AddField(
model_name="homepage",
name="body",
field=wagtail.core.fields.RichTextField(blank=True),
),
]
32 changes: 32 additions & 0 deletions home/migrations/0004_standardpage_story.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Generated by Django 4.0.7 on 2022-10-03 20:46

import wagtail.core.blocks
import wagtail.core.fields
import wagtail.images.blocks
from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
("home", "0003_standardpage_homepage_body"),
]

operations = [
migrations.AddField(
model_name="standardpage",
name="story",
field=wagtail.core.fields.StreamField(
[
(
"heading",
wagtail.core.blocks.CharBlock(form_classname="full title"),
),
("paragraph", wagtail.core.blocks.RichTextBlock()),
("image", wagtail.images.blocks.ImageChooserBlock()),
],
blank=True,
null=True,
),
),
]
Loading