Нема описа

seed_cms.py 3.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. from __future__ import annotations
  2. from django.core.management.base import BaseCommand
  3. import os
  4. from pathlib import Path
  5. from django.conf import settings
  6. from django.core.files import File
  7. from cms.models import create_demo_data, PostCategory, Post
  8. from orgs.models import Organization
  9. class Command(BaseCommand):
  10. help = "Seed demo categories and posts for the CMS app (optionally per organization)"
  11. def handle(self, *args, **options):
  12. org_ident = options.get("org")
  13. org = None
  14. if org_ident:
  15. if org_ident.isdigit():
  16. org = Organization.objects.filter(pk=int(org_ident)).first()
  17. if org is None:
  18. org = Organization.objects.filter(code=org_ident).first() or Organization.objects.filter(name=org_ident).first()
  19. if org is None:
  20. raise SystemExit(self.style.ERROR(f"Organization not found: {org_ident}"))
  21. # Ensure root category per org if org is provided
  22. if org is not None:
  23. root_name = f"{org.code}_root"
  24. root_slug = f"{org.code}-root"
  25. root, _ = PostCategory.objects.get_or_create(
  26. organization=org,
  27. slug=root_slug,
  28. defaults={
  29. "name": root_name,
  30. "parent": None,
  31. "description": f"Root category for {org.code}",
  32. },
  33. )
  34. result = create_demo_data(org=org)
  35. # Move all top-level categories under the root (excluding the root itself)
  36. if org is not None:
  37. # Re-fetch root to be safe
  38. root = PostCategory.objects.get(organization=org, slug=f"{org.code}-root")
  39. top_levels = PostCategory.objects.filter(organization=org, parent__isnull=True).exclude(pk=root.pk)
  40. for cat in top_levels:
  41. cat.parent = root
  42. cat.save()
  43. # Attach demo feature images from static/demo/ if available
  44. try:
  45. demo_dir = Path(settings.BASE_DIR) / "static" / "demo"
  46. if demo_dir.exists() and demo_dir.is_dir():
  47. image_files = [p for p in sorted(demo_dir.iterdir()) if p.suffix.lower() in {".jpg", ".jpeg", ".png", ".webp", ".gif"}]
  48. else:
  49. image_files = []
  50. except Exception:
  51. image_files = []
  52. if image_files:
  53. posts_qs = Post.objects.all().order_by("id")
  54. if org is not None:
  55. posts_qs = posts_qs.filter(organization=org)
  56. idx = 0
  57. for post in posts_qs:
  58. if not getattr(post, "feature_image", None) or not post.feature_image:
  59. img_path = image_files[idx % len(image_files)]
  60. try:
  61. with open(img_path, "rb") as fh:
  62. post.feature_image.save(img_path.name, File(fh), save=True)
  63. except Exception:
  64. # Skip on any IO error and continue with next
  65. pass
  66. idx += 1
  67. suffix = f" for org {org.code}" if org else ""
  68. self.stdout.write(self.style.SUCCESS(
  69. f"CMS demo data seeded{suffix}: categories={result.get('categories', 0)}, posts={result.get('posts', 0)}"
  70. ))
  71. def add_arguments(self, parser):
  72. parser.add_argument("--org", help="Organization code, id, or name to seed CMS data for", default=None)