This commit is contained in:
parent
1aad42cb83
commit
21c4d803dd
1 changed files with 19 additions and 17 deletions
36
slides.md
36
slides.md
|
@ -33,12 +33,12 @@ background: /intranet.png
|
|||
|
||||
<!--
|
||||
- People usually use Wagtail as a website or blog
|
||||
- But it works really well as an intranet too
|
||||
- At Torchbox, we use it for internal documentation ("intranet")
|
||||
- Processes
|
||||
- Company information
|
||||
- Links to other places etc
|
||||
- Been around for a while
|
||||
- Slowly growing
|
||||
- In 2022, we restructured the content
|
||||
- Make it easier to find things
|
||||
- Remove duplication
|
||||
|
@ -56,11 +56,12 @@ background: /site-history.png
|
|||
|
||||
<!--
|
||||
- First step: Understanding what happened
|
||||
- Wagtail has me covered there
|
||||
- The site history report!
|
||||
- Fortunately, Wagtail showed _almost_ exactly what had happened, and what I expected
|
||||
- Fortunately, Wagtail showed _almost_ exactly what had happened
|
||||
- One staff member deleted the "Sysadmin" section a few days before
|
||||
- Which deleted every page under it, all 105 of them
|
||||
- "Radical reorganisation"
|
||||
- Which deleted every page under it
|
||||
- All 105 of them
|
||||
-->
|
||||
|
||||
---
|
||||
|
@ -76,6 +77,7 @@ backgroundSize: contain
|
|||
- They'd made a new "Sysadmin" section a while ago, before switching strategy to move pages in the existing tree
|
||||
- They then deleted the wrong one
|
||||
- Sure, Wagtail shows a confirmation when you're deleting pages, but when you're deleting a lot of pages, and expecting to delete pages, you might not read the message perfectly
|
||||
- "Radical reorganisation" my boss called it
|
||||
- With the content gone, I had to restore from backups.
|
||||
-->
|
||||
|
||||
|
@ -100,7 +102,7 @@ layout: section
|
|||
|
||||
<!--
|
||||
- Ideally, what I needed was to restore only the sysadmin pages, leaving all others completely untouched.
|
||||
- Using a few tricks of Django and Wagtail internals, it's absolutely possible, and we did it
|
||||
- Using a few tricks of Django and Wagtail internals, it's absolutely possible, and I did it
|
||||
- With 0 downtime, too!
|
||||
-->
|
||||
|
||||
|
@ -113,7 +115,7 @@ layout: section
|
|||
|
||||
<!--
|
||||
- We backup our intranet nightly, so I downloaded a backup from before the incident
|
||||
- Start the codebase locally so I can interrogate it
|
||||
- Spin up the codebase locally so I can interrogate it
|
||||
-->
|
||||
|
||||
---
|
||||
|
@ -138,7 +140,7 @@ child_pages = sysadmin_page.get_descendants()
|
|||
<!--
|
||||
- Behind the scenes, Wagtail pages are a tree, implemented using `django-treebeard`.
|
||||
- When a page is deleted, treebeard is the one who finds all the child pages and deletes them too
|
||||
- And then Django and postgres deal with cascading the delete
|
||||
- And then Django and the database deal with cascading the delete
|
||||
-->
|
||||
|
||||
---
|
||||
|
@ -160,13 +162,13 @@ collector.collect(list(child_pages) + [sysadmin_page])
|
|||
</div>
|
||||
|
||||
<!--
|
||||
This is where the magic happens
|
||||
- This is where the magic happens
|
||||
- Deleting a page deletes more than just a page
|
||||
- The specific model
|
||||
- Revisions
|
||||
- Related models
|
||||
- Through tables
|
||||
- `get_descendants` won't get all those
|
||||
- `get_descendants` won't get all those
|
||||
- Calling `.delete` gives you the number of objects, and it's quite a lot
|
||||
- If you've ever used the Django admin, you know it's capable of finding every model instance before a delete
|
||||
- That's implemented with an undocumented but simple to use API
|
||||
|
@ -212,7 +214,7 @@ with open("deleted-models.json", "w") as f:
|
|||
<!--
|
||||
- `collector.data` now contains all the model instances which were deleted, in memory on my laptop
|
||||
- My laptop isn't what's running production
|
||||
- Need to serialize the models into an intermdiary format which can be then be loaded onto production
|
||||
- Need to serialize the models so they can be then be loaded onto production
|
||||
- If you're thinking of fixtures, you're right
|
||||
- Django's fixtures create a JSON representation of a model, so they can be saved in 1 location and loaded into another
|
||||
- Mostly useful for complex test fixtures (hence the name), but generally useful for cases like this
|
||||
|
@ -220,7 +222,7 @@ with open("deleted-models.json", "w") as f:
|
|||
- When Django serializes a model with a m2m which doesn't use a custom table, it inlines the definition, because it's easier to work with
|
||||
- However, `NestedObjects` still finds these through tables, and tries to load them separately
|
||||
- Resulting in duplicate objects and referential integrity issues
|
||||
- Instead, we exclude them
|
||||
- Instead, we exclude them, knowing we picked them up explicitly with `NestedObjects`
|
||||
-->
|
||||
|
||||
---
|
||||
|
@ -295,7 +297,6 @@ layout: fact
|
|||
- The search index objects (we use postgres) were picked up by `NestedObjects`
|
||||
- They didn't like being restored
|
||||
- So I skipped them and moved on, knowing I'd just rebuild the index later.
|
||||
- `manage.py fixtree` also reports any tree issues, which there weren't
|
||||
-->
|
||||
|
||||
---
|
||||
|
@ -322,13 +323,14 @@ class: flex justify-center flex-col items-center
|
|||
- The tense bit
|
||||
- Once I was happy, I ran the same steps on production
|
||||
- Our intranet runs on Heroku, so I had to do a few dances to get the JSON file up there.
|
||||
- [click]Before I began, I did a backup, because I'm a good sysadmin
|
||||
- [click]With the data file in place, [click]I crossed everything and ran `loaddata`
|
||||
- [click]Before I began, I did a backup
|
||||
- Because I'm a good sysadmin
|
||||
- [click]With the data file in place, I crossed everything[click] and ran `loaddata`
|
||||
- Pages popped up in the admin as if they never left
|
||||
- [click]`checktree` worked.
|
||||
- [click]`update_index` worked.
|
||||
- [click] As did `rebuild_reference_index`
|
||||
- The new pages were now findable
|
||||
- The new pages were now findable and searchable
|
||||
-->
|
||||
|
||||
---
|
||||
|
@ -344,9 +346,9 @@ background: /sysadmin.png
|
|||
- No content freeze
|
||||
- No data loss
|
||||
- Most people didn't even know there was an issue
|
||||
- I've used this trick a a few times in my career, for both Wagtail and plain Django sites
|
||||
- I've used this trick a few times in my career, for both Wagtail and plain Django sites
|
||||
- Ironically, just a few weeks after the blog post was published
|
||||
- Works identically for Django sites, so long as you know how to reconstruct the delete query.
|
||||
- Works identically for any Django project, so long as you know how to reconstruct the delete query.
|
||||
- Hopefully this helps you out as much as it has me!
|
||||
-->
|
||||
|
||||
|
|
Loading…
Reference in a new issue