1
Fork 0
recovering-deleted-wagtail-.../slides.md

3.5 KiB

title class highlighter transition mdc themeConfig addons
Recovering deleted Wagtail pages and Django models text-center shiki slide-left true
primary
#fd5765
slidev-addon-qrcode

Recovering [deleted]{style="color: #fd5765"} Wagtail pages and Django models

Jake Howard

  • Senior Systems Engineer @ Torchbox
  • Security Team & Performance Working Group @ Wagtail
  • theorangeone.net
  • @RealOrangeOne
  • @RealOrangeOne
  • @jake@theorangeone.net

layout: cover background: https://cdn.jsdelivr.net/gh/wagtail/wagtail@main/.github/wagtail-screenshot-with-browser.png

Setting the scene


layout: cover

Site history report


layout: section

Restoring from backups


layout: section

Partial restores from backups


layout: section

1.

Spin up a database backup


layout: section

2.

Locate the page models

from wagtail.models import Page

sysadmin_page = Page.objects.get(id=91)

child_pages = sysadmin_page.get_descendants()

layout: section

3.

Locate what was deleted

from django.contrib.admin.utils import NestedObjects

collector = NestedObjects()
collector.collect(list(child_pages) + [sysadmin_page])

layout: section

4. Serialize

from django.core import serializers

class NoM2MSerializer(Serializer):
    def handle_m2m_field(self, obj, field):
        pass

def get_model_instances():
    for qs in collector.data.values():
        yield from qs

with open("deleted-models.json", "w") as f:
    NoM2MSerializer().serialize(
        get_model_instances(),
        stream=f
    )

layout: section

4a.

Deserialize


layout: center

restore-deleted-pages.py

from django.contrib.admin.utils import NestedObjects
from django.core import serializers

from wagtail.models import Page

class NoM2MSerializer(Serializer):
    def handle_m2m_field(self, obj, field):
        pass

sysadmin_page = Page.objects.get(id=91)

child_pages = sysadmin_page.get_descendants()

collector = NestedObjects()
collector.collect(list(child_pages) + [sysadmin_page])

def get_model_instances():
    for qs in collector.data.values():
        yield from qs

with open("deleted-models.json", "w") as f:
    NoM2MSerializer().serialize(
        get_model_instances(),
        stream=f
    )

layout: section

5.

Test

Test

Test!


layout: image-right image: /red-button.png class: flex justify-center flex-col items-center

6.

Showtime!


layout: cover background: https://cdn.jsdelivr.net/gh/wagtail/wagtail@main/.github/wagtail-screenshot-with-browser.png

Conclusion


layout: end

END