first deployment of kikomiko with url photos
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
co-authored by
Cursor
parent
8d98304137
commit
ae3ed7c7b7
@@ -0,0 +1,114 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Import a full catalog.json into the admin SQLite DB (no HTTP / no size limit).
|
||||
|
||||
Usage:
|
||||
python3 import_catalog.py /path/to/catalog.json
|
||||
python3 import_catalog.py /path/to/catalog.json --export
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
# Reuse server helpers
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parent))
|
||||
import server # noqa: E402
|
||||
|
||||
|
||||
def map_export_category(raw: dict) -> dict:
|
||||
"""Map export {id,parent_id,name,full_path} -> admin category row fields."""
|
||||
name = str(raw.get("name") or raw.get("full_path") or "").strip()
|
||||
if not name:
|
||||
raise ValueError("category missing name")
|
||||
slug = str(raw.get("slug") or server._slugify(name))
|
||||
parent_slug = None
|
||||
parent_id = raw.get("parent_id") or raw.get("parentSlug") or raw.get("parent_slug")
|
||||
if parent_id:
|
||||
parent_name = str(parent_id).split(" / ")[-1].strip()
|
||||
parent_slug = server._slugify(parent_name)
|
||||
return {
|
||||
"slug": slug,
|
||||
"name": name.title() if name == name.upper() else name,
|
||||
"name_fa": str(raw.get("name_fa") or raw.get("nameFa") or ""),
|
||||
"parent_slug": parent_slug,
|
||||
"sort_order": int(raw.get("sort_order") or raw.get("sortOrder") or 0),
|
||||
"active": raw.get("active", True),
|
||||
}
|
||||
|
||||
|
||||
def import_categories(payload: dict) -> int:
|
||||
cats = payload.get("categories") or []
|
||||
if not isinstance(cats, list):
|
||||
return 0
|
||||
# parents first (shorter paths)
|
||||
cats = sorted(cats, key=lambda c: str(c.get("full_path") or c.get("id") or "").count("/"))
|
||||
count = 0
|
||||
with server.db() as conn:
|
||||
for raw in cats:
|
||||
if not isinstance(raw, dict):
|
||||
continue
|
||||
try:
|
||||
server.upsert_category(conn, map_export_category(raw))
|
||||
count += 1
|
||||
except Exception as exc:
|
||||
print(f" category skip: {exc}", file=sys.stderr)
|
||||
return count
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Import catalog.json into admin DB")
|
||||
parser.add_argument("catalog", type=Path, help="Path to catalog.json")
|
||||
parser.add_argument(
|
||||
"--export",
|
||||
action="store_true",
|
||||
help="Also export active products to storefront catalog.dedupe2.json",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--products-only",
|
||||
action="store_true",
|
||||
help="Skip categories",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
path = args.catalog.expanduser().resolve()
|
||||
if not path.is_file():
|
||||
print(f"File not found: {path}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
print(f"Loading {path} ({path.stat().st_size // 1_000_000} MB)…")
|
||||
payload = json.loads(path.read_text(encoding="utf-8"))
|
||||
if not isinstance(payload, (dict, list)):
|
||||
print("Invalid JSON root", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
server.init_db()
|
||||
|
||||
if isinstance(payload, dict) and not args.products_only:
|
||||
n = import_categories(payload)
|
||||
print(f"Categories imported/updated: {n}")
|
||||
|
||||
print("Importing products…")
|
||||
result = server.import_products_payload(payload)
|
||||
print(
|
||||
f"Products created={result['created']} updated={result['updated']} "
|
||||
f"skipped={result['skipped']} errors={len(result['errors'])}"
|
||||
)
|
||||
if result["errors"]:
|
||||
print("First errors:", file=sys.stderr)
|
||||
for err in result["errors"][:10]:
|
||||
print(f" {err}", file=sys.stderr)
|
||||
|
||||
if args.export:
|
||||
out = server.export_catalog()
|
||||
print(f"Exported {out['count']} products → {out['path']}")
|
||||
|
||||
with server.db() as conn:
|
||||
pc = conn.execute("SELECT COUNT(*) AS c FROM products").fetchone()["c"]
|
||||
cc = conn.execute("SELECT COUNT(*) AS c FROM categories").fetchone()["c"]
|
||||
print(f"DB totals: products={pc} categories={cc}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user