Add demo data purge command
This commit is contained in:
2
Jenkinsfile
vendored
2
Jenkinsfile
vendored
@@ -82,7 +82,7 @@ PY
|
|||||||
pip install ruff vdt.versionplugin.wheel
|
pip install ruff vdt.versionplugin.wheel
|
||||||
pip install --upgrade "setuptools==69.5.1" wheel
|
pip install --upgrade "setuptools==69.5.1" wheel
|
||||||
manage.py migrate --no-input --skip-checks
|
manage.py migrate --no-input --skip-checks
|
||||||
manage.py purge_demo_data
|
manage.py purge_demo_data --keep-only-idea-products
|
||||||
manage.py collectstatic --no-input --verbosity=0
|
manage.py collectstatic --no-input --verbosity=0
|
||||||
pip install "httpx<0.28"
|
pip install "httpx<0.28"
|
||||||
'''
|
'''
|
||||||
|
|||||||
120
mandelstudio/management/commands/purge_demo_data.py
Normal file
120
mandelstudio/management/commands/purge_demo_data.py
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
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} 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
|
||||||
|
|
||||||
|
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)
|
||||||
|
for product in iterable:
|
||||||
|
removed += 1
|
||||||
|
self.stdout.write(
|
||||||
|
f"PRODUCT {'[dry-run] ' if dry_run else ''}delete id={product.id} title={product.title}"
|
||||||
|
)
|
||||||
|
if not dry_run:
|
||||||
|
product.delete()
|
||||||
|
return removed
|
||||||
Reference in New Issue
Block a user