Skip to content

Seed Data & Catalog Management

This guide covers managing seed data for development, staging, and production environments, including strategies for incremental catalog updates.

Overview

The seed data system allows you to version-control your complete webshop catalog and automatically deploy it across environments via CI/CD. This ensures consistency between development, staging, and production.

What Gets Exported/Imported

Database Models (21 Total)

App Model Description
core SiteSettings Store settings, VAT, shipping, footer info
core Page Static pages (Terms, Privacy, FAQ, About, Returns)
products Category Product categories (hierarchical with MPTT)
products Brand Product brands with logos
products Product Products with specifications
products Color Available product colors
products Size Available sizes (clothing, caps, accessories)
products ProductColorImage Multi-view images per color
products ProductVariant Size/color combinations with stock
pricing DiscountCode Promotional discount codes
pricing VolumeDiscount Bulk purchase discounts
pricing VolumeDiscountTier Volume discount tiers
pricing TeamDiscount Team order discounts
pricing SpecialOffer Time-limited promotions
pricing PricingRule Dynamic pricing rules
designs Font Designer fonts (uploaded + Google)
designs TextColor Designer text colors with pricing
designs DesignTemplate Pre-made design templates
clipart ClipartCategory Clipart categories
clipart ClipartItem Individual clipart SVGs

Media Files

Directory Contents
products/ Product main images
categories/ Category thumbnails
brands/ Brand logos
variants/ Variant-specific images
fonts/ Uploaded font files (.ttf, .otf, .woff, .woff2)
clipart/ SVG files and thumbnails
templates/ Design template thumbnails

What's NOT Included (Runtime Data)

  • Orders, OrderItems, CartItems
  • CustomDesigns (user-created)
  • User accounts
  • Payment transactions

Seed data is stored in backend/fixtures/seed/ and version-controlled:

backend/fixtures/seed/
├── seed_data.json      # All catalog data
├── metadata.json       # Export metadata
└── media/              # Product images, fonts, clipart
    ├── products/
    ├── categories/
    ├── fonts/
    └── clipart/

Commands

Export Seed Data

# Using helper script (recommended)
./scripts/export-seed-data.sh

# Direct Django command
cd backend
python manage.py export_seed_data

# Export without images (JSON only)
python manage.py export_seed_data --skip-images

# Export to custom location
python manage.py export_seed_data --output /tmp/my_export

Import Seed Data

# Standard import (merge mode - updates existing, creates new)
python manage.py import_seed_data

# Import new records only, skip existing
python manage.py import_seed_data --mode skip

# Import with detailed logging
python manage.py import_seed_data --mode overwrite

# Clear all catalog data before import (dangerous!)
python manage.py import_seed_data --clear --force

# Import from custom location
python manage.py import_seed_data --input /path/to/seed_data

Import Modes

Mode Behavior
merge (default) Update existing records, create new ones
skip Only create new records, skip existing
overwrite Same as merge with detailed logging

Selective Export (Specific Models)

For updating specific parts of the catalog without a full export:

# Export only products
./manage.sh update-catalog products

# Export specific product (by SKU)
./manage.sh update-catalog products 'sku=HOODIE-BLUE-001'

# Export only pricing rules
./manage.sh update-catalog 'discount_codes,volume_discounts'

# Export a category and its products
./manage.sh update-catalog 'categories,products' 'category__slug=hoodies'

Available models for selective export: products, categories, brands, colors, sizes, product_variants, product_color_images, discount_codes, volume_discounts, team_discounts, special_offers, pricing_rules, site_settings

Catalog Update Strategies

After the initial catalog import, use the appropriate strategy for ongoing updates.

Strategy 1: Merge Import (Multiple Updates)

Best for updating multiple products, refreshing pricing, or adding new products alongside existing ones.

The import command uses update_or_create() by default:

  • Existing records (matched by primary key) are updated
  • New records are created
  • Existing records not in the import are preserved
# On development: Make changes in Django admin
# Export the catalog
./scripts/export-seed-data.sh

# On staging/production: Import (merges with existing)
python manage.py import_seed_data

Strategy 2: Selective Export (Specific Updates)

Best for updating a single product, specific pricing rules, or a specific category.

# Update single product description
./manage.sh update-catalog products 'sku=TSHIRT-BASIC-001'

# Update all discount codes
./manage.sh update-catalog 'discount_codes,volume_discounts,team_discounts'

# Add new color to existing product
./manage.sh update-catalog 'colors,products,product_color_images,product_variants' 'product__sku=HOODIE-001'

Tip

Use --include-related to automatically include related records, or explicitly list related models.

Strategy 3: Direct Django Admin (Single Changes)

Best for fixing a typo, adjusting one price, or toggling a flag. Make changes directly in the target environment's Django admin -- no export/import needed.

Comparison

Strategy Use Case Speed Safety Complexity
Merge Import Multiple updates, new products Slow High Low
Selective Export Specific products/models Fast High Medium
Direct Admin Single field changes Instant Medium Low

Workflow by Environment

Development

# Make catalog changes in Django admin
# Then export to version control
./scripts/export-seed-data.sh
git add backend/fixtures/seed/
git commit -m "feat(catalog): add new product line"

Staging (Automatic via CI/CD)

Seed data is automatically imported on every deployment to the main branch:

  1. CI/CD copies backend/fixtures/seed/ to staging server
  2. After deployment, runs import_seed_data --mode merge
  3. Staging always reflects the latest catalog from git

Production

For production, use a hybrid approach:

# Initial setup: Import baseline catalog
python manage.py import_seed_data --mode skip --force

# Ongoing: Use Django admin for catalog changes
# Major updates: Export from staging, review, import to production

CI/CD Integration

Automatic Testing (ci.yml)

The CI pipeline tests seed data export/import on every push:

  1. Creates a minimal test fixture (1 product, 1 category, 1 color, 1 size, 1 variant)
  2. Exports to /tmp with --skip-images
  3. Flushes database
  4. Imports and validates data integrity
  5. Tests git-tracked seed data import (if exists)

Staging Deployment (deploy-staging.yml)

# Seed data is automatically deployed:
- name: Copy seed data to server
  # Copies backend/fixtures/seed/ to staging

- name: Import seed data (staging only)
  # Runs: python manage.py import_seed_data --mode merge --force

Adding New Models to CI Testing

  1. Update create_test_fixture.py -- add 1 instance of the new model
  2. Update CI verification assertions in .github/workflows/ci.yml
  3. Test locally before committing

Best Practices

  1. Always export after admin changes -- Keep git-tracked seed data current
  2. Review before committing -- git diff fixtures/seed/seed_data.json
  3. Test on staging first -- Staging auto-imports on deploy
  4. Production via admin -- Use Django admin for ongoing changes
  5. Version large updates -- Create git tags for major catalog changes
  6. Backup before importing -- Export production data before major catalog changes
  7. Use selective exports for efficiency -- For large catalogs (1000+ products), don't export/import everything for small changes

Troubleshooting

Import Fails with Foreign Key Error

Ensure full export is being imported. Dependencies are imported in order. If using selective export, include all related models:

# Wrong: Export only products
./manage.sh update-catalog products

# Right: Export products AND their dependencies
./manage.sh update-catalog 'categories,brands,products'

Images Not Showing

Check MEDIA_ROOT and MEDIA_URL settings. Ensure web server can serve media files. If using DigitalOcean Spaces, upload paths should be relative (e.g., products/image.png not media/products/image.png).

Import Overwrites Custom Production Changes

Production-specific changes (like stock levels) get overwritten. Solution: Use Django admin for those fields, or manage them via selective export excluding those fields.

Large Media Files

Product images and media files are stored on DigitalOcean Spaces (S3-compatible object storage). Seed data media files in backend/fixtures/seed/media/ are version-controlled in the repository. During import, files are uploaded to the configured storage backend (local filesystem in development, DigitalOcean Spaces in staging/production).

CI Test Failures

Error Cause Solution
"Expected X records, got Y" Fixture/import logic changed Check create_test_fixture.py and CI assertions
"JSON serialization error" New field type not handled Update DecimalEncoder in export_seed_data.py
"Foreign key constraint" Import order issue Check import_order list in import_database_data()

Technical Details

Security Features

  • Model whitelist prevents importing unauthorized models
  • Path traversal protection on image imports
  • File size limits (100MB max)
  • Symlink following disabled

Export Format

  • Database: Django JSON serialization with natural foreign keys
  • Images: Direct file copy preserving directory structure
  • Metadata: Export timestamp and record counts