101 lines
3.4 KiB
Python
101 lines
3.4 KiB
Python
|
|
"""
|
||
|
|
Seed the default AdSurface records and migrate existing boolean flags to placements.
|
||
|
|
|
||
|
|
Usage:
|
||
|
|
python manage.py seed_surfaces # seed surfaces only
|
||
|
|
python manage.py seed_surfaces --migrate # also migrate is_featured / is_top_event to placements
|
||
|
|
"""
|
||
|
|
from django.core.management.base import BaseCommand
|
||
|
|
from ad_control.models import AdSurface, AdPlacement
|
||
|
|
from events.models import Event
|
||
|
|
|
||
|
|
|
||
|
|
SURFACES = [
|
||
|
|
{
|
||
|
|
'key': 'HOME_FEATURED_CAROUSEL',
|
||
|
|
'name': 'Featured Carousel',
|
||
|
|
'description': 'Homepage hero carousel — high-impact banner-style placement.',
|
||
|
|
'max_slots': 8,
|
||
|
|
'layout_type': 'carousel',
|
||
|
|
'sort_behavior': 'rank',
|
||
|
|
},
|
||
|
|
{
|
||
|
|
'key': 'HOME_TOP_EVENTS',
|
||
|
|
'name': 'Top Events',
|
||
|
|
'description': 'Homepage "Top Events" grid section below the hero.',
|
||
|
|
'max_slots': 10,
|
||
|
|
'layout_type': 'grid',
|
||
|
|
'sort_behavior': 'rank',
|
||
|
|
},
|
||
|
|
]
|
||
|
|
|
||
|
|
|
||
|
|
class Command(BaseCommand):
|
||
|
|
help = 'Seed default ad surfaces and optionally migrate boolean flags to placements.'
|
||
|
|
|
||
|
|
def add_arguments(self, parser):
|
||
|
|
parser.add_argument(
|
||
|
|
'--migrate',
|
||
|
|
action='store_true',
|
||
|
|
help='Also migrate existing is_featured / is_top_event flags to AdPlacement rows.',
|
||
|
|
)
|
||
|
|
|
||
|
|
def handle(self, *args, **options):
|
||
|
|
# --- Seed surfaces ---
|
||
|
|
for s in SURFACES:
|
||
|
|
obj, created = AdSurface.objects.update_or_create(
|
||
|
|
key=s['key'],
|
||
|
|
defaults=s,
|
||
|
|
)
|
||
|
|
status = 'CREATED' if created else 'EXISTS'
|
||
|
|
self.stdout.write(f" [{status}] {obj.key} — {obj.name}")
|
||
|
|
|
||
|
|
# --- Migrate boolean flags ---
|
||
|
|
if options['migrate']:
|
||
|
|
self.stdout.write('\nMigrating boolean flags to placements...')
|
||
|
|
|
||
|
|
featured_surface = AdSurface.objects.get(key='HOME_FEATURED_CAROUSEL')
|
||
|
|
top_surface = AdSurface.objects.get(key='HOME_TOP_EVENTS')
|
||
|
|
|
||
|
|
featured_events = Event.objects.filter(is_featured=True)
|
||
|
|
top_events = Event.objects.filter(is_top_event=True)
|
||
|
|
|
||
|
|
created_count = 0
|
||
|
|
|
||
|
|
for rank, event in enumerate(featured_events, start=1):
|
||
|
|
_, created = AdPlacement.objects.get_or_create(
|
||
|
|
surface=featured_surface,
|
||
|
|
event=event,
|
||
|
|
defaults={
|
||
|
|
'status': 'ACTIVE',
|
||
|
|
'priority': 'MANUAL',
|
||
|
|
'scope': 'GLOBAL',
|
||
|
|
'rank': rank,
|
||
|
|
'boost_label': 'Featured',
|
||
|
|
},
|
||
|
|
)
|
||
|
|
if created:
|
||
|
|
created_count += 1
|
||
|
|
|
||
|
|
for rank, event in enumerate(top_events, start=1):
|
||
|
|
_, created = AdPlacement.objects.get_or_create(
|
||
|
|
surface=top_surface,
|
||
|
|
event=event,
|
||
|
|
defaults={
|
||
|
|
'status': 'ACTIVE',
|
||
|
|
'priority': 'MANUAL',
|
||
|
|
'scope': 'GLOBAL',
|
||
|
|
'rank': rank,
|
||
|
|
'boost_label': 'Top Event',
|
||
|
|
},
|
||
|
|
)
|
||
|
|
if created:
|
||
|
|
created_count += 1
|
||
|
|
|
||
|
|
self.stdout.write(self.style.SUCCESS(
|
||
|
|
f' Migrated {created_count} placements '
|
||
|
|
f'({featured_events.count()} featured, {top_events.count()} top events).'
|
||
|
|
))
|
||
|
|
|
||
|
|
self.stdout.write(self.style.SUCCESS('\nDone.'))
|