from __future__ import annotations from django.core.management.base import BaseCommand import os from pathlib import Path from django.conf import settings from django.core.files import File from cms.models import create_demo_data, PostCategory, Post from orgs.models import Organization class Command(BaseCommand): help = "Seed demo categories and posts for the CMS app (optionally per organization)" def handle(self, *args, **options): org_ident = options.get("org") org = None if org_ident: if org_ident.isdigit(): org = Organization.objects.filter(pk=int(org_ident)).first() if org is None: org = Organization.objects.filter(code=org_ident).first() or Organization.objects.filter(name=org_ident).first() if org is None: raise SystemExit(self.style.ERROR(f"Organization not found: {org_ident}")) # Ensure root category per org if org is provided if org is not None: root_name = f"{org.code}_root" root_slug = f"{org.code}-root" root, _ = PostCategory.objects.get_or_create( organization=org, slug=root_slug, defaults={ "name": root_name, "parent": None, "description": f"Root category for {org.code}", }, ) result = create_demo_data(org=org) # Move all top-level categories under the root (excluding the root itself) if org is not None: # Re-fetch root to be safe root = PostCategory.objects.get(organization=org, slug=f"{org.code}-root") top_levels = PostCategory.objects.filter(organization=org, parent__isnull=True).exclude(pk=root.pk) for cat in top_levels: cat.parent = root cat.save() # Attach demo feature images from static/demo/ if available try: demo_dir = Path(settings.BASE_DIR) / "static" / "demo" if demo_dir.exists() and demo_dir.is_dir(): image_files = [p for p in sorted(demo_dir.iterdir()) if p.suffix.lower() in {".jpg", ".jpeg", ".png", ".webp", ".gif"}] else: image_files = [] except Exception: image_files = [] if image_files: posts_qs = Post.objects.all().order_by("id") if org is not None: posts_qs = posts_qs.filter(organization=org) idx = 0 for post in posts_qs: if not getattr(post, "feature_image", None) or not post.feature_image: img_path = image_files[idx % len(image_files)] try: with open(img_path, "rb") as fh: post.feature_image.save(img_path.name, File(fh), save=True) except Exception: # Skip on any IO error and continue with next pass idx += 1 suffix = f" for org {org.code}" if org else "" self.stdout.write(self.style.SUCCESS( f"CMS demo data seeded{suffix}: categories={result.get('categories', 0)}, posts={result.get('posts', 0)}" )) def add_arguments(self, parser): parser.add_argument("--org", help="Organization code, id, or name to seed CMS data for", default=None)