Files
mandelstudio/mandelstudio/management/commands/purge_demo_data.py

148 lines
4.4 KiB
Python

from __future__ import annotations
from dataclasses import dataclass
from django.core.management.base import BaseCommand
IDEA_PRODUCT_TITLES = {
"B2B Webshop Starter Blueprint",
"AI Product Description System",
"High-Converting Landing Page Framework",
"Subscription-Based Service Website Model",
"Marketplace Platform Architecture (Django)",
}
@dataclass(frozen=True)
class PurgeStats:
pages: int = 0
products: int = 0
class Command(BaseCommand):
help = (
"Remove demo pages/products from Mandel Blog while preserving "
"idea marketplace content."
)
def add_arguments(self, parser):
parser.add_argument(
"--dry-run",
action="store_true",
help="Show what would be removed without deleting.",
)
parser.add_argument(
"--keep-only-idea-products",
action="store_true",
help="Delete all products except the 5 idea marketplace products.",
)
def handle(self, *args, **options):
dry_run = bool(options["dry_run"])
keep_only_idea_products = bool(options["keep_only_idea_products"])
page_count = self._purge_pages(dry_run=dry_run)
product_count = self._purge_products(
dry_run=dry_run,
keep_only_idea_products=keep_only_idea_products,
)
stats = PurgeStats(pages=page_count, products=product_count)
mode = "DRY RUN" if dry_run else "APPLIED"
self.stdout.write(
self.style.SUCCESS(
f"[{mode}] Removed pages={stats.pages}, products={stats.products}"
)
)
def _purge_pages(self, *, dry_run: bool) -> int:
from wagtail.models import Page
slug_markers = [
"starter-website",
"business-website",
"demo",
"voorbeeld",
"sample",
"template",
]
title_markers = [
"starter website",
"business website",
"demo",
"voorbeeld",
"sample",
"template",
]
qs = Page.objects.exclude(depth=1).exclude(slug__in=["home"]).specific()
candidates = []
for page in qs:
slug = (page.slug or "").lower()
title = (page.title or "").lower()
if any(marker in slug for marker in slug_markers) or any(
marker in title for marker in title_markers
):
candidates.append(page)
removed = 0
for page in candidates:
removed += 1
self.stdout.write(
f"PAGE {'[dry-run] ' if dry_run else ''}delete id={page.id} "
f"slug={page.slug} title={page.title}"
)
if not dry_run:
page.delete()
return removed
def _purge_products(self, *, dry_run: bool, keep_only_idea_products: bool) -> int:
from oscar.core.loading import get_model
from oscar_elasticsearch.search.signal_handlers import (
deregister_signal_handlers,
register_signal_handlers,
)
Product = get_model("catalogue", "Product")
products = Product.objects.all()
if keep_only_idea_products:
candidates = products.exclude(title__in=IDEA_PRODUCT_TITLES)
else:
title_markers = [
"demo",
"sample",
"placeholder",
"starter website",
"business website",
]
candidates = [
p
for p in products
if any(marker in (p.title or "").lower() for marker in title_markers)
]
removed = 0
iterable = candidates if isinstance(candidates, list) else list(candidates)
if dry_run:
for product in iterable:
removed += 1
self.stdout.write(
f"PRODUCT [dry-run] delete id={product.id} title={product.title}"
)
return removed
deregister_signal_handlers()
try:
for product in iterable:
removed += 1
self.stdout.write(
f"PRODUCT delete id={product.id} title={product.title}"
)
product.delete()
finally:
register_signal_handlers()
return removed