feat: build headless theatre laboratory website

This commit is contained in:
bisco
2026-06-22 19:42:43 +02:00
parent cae9180bc6
commit cff9a17c3c
65 changed files with 8994 additions and 128 deletions
@@ -0,0 +1,212 @@
from io import BytesIO
from django.core.files.base import ContentFile
from django.core.management.base import BaseCommand
from PIL import Image as PillowImage
from wagtail.images import get_image_model
from wagtail.models import Page, Site
from home.models import GalleryItem, HomePage, LessonInfo, Show, SiteSettings, TeacherProfile
class Command(BaseCommand):
help = "Create or refresh the Italian demo content without creating duplicates."
def placeholder(self, title: str, filename: str, color: str):
image_model = get_image_model()
existing = image_model.objects.filter(title=title).first()
if existing:
return existing
output = BytesIO()
PillowImage.new("RGB", (1200, 800), color=color).save(
output,
format="JPEG",
quality=85,
)
return image_model.objects.create(
title=title,
file=ContentFile(output.getvalue(), name=filename),
)
def handle(self, *args, **options):
hero_image = self.placeholder("Prova in sala", "demo-hero.jpg", "#D8C7AE")
laboratory_image = self.placeholder(
"Esercizio di gruppo", "demo-laboratory.jpg", "#A9A497"
)
teacher_image = self.placeholder("Il maestro", "demo-teacher.jpg", "#B8674C")
show_image = self.placeholder("Locandina Tracce", "demo-show.jpg", "#515D53")
second_show_image = self.placeholder(
"Locandina Sottovoce", "demo-show-sottovoce.jpg", "#B8674C"
)
gallery_images = [
self.placeholder("Lezione", "demo-gallery-lesson.jpg", "#D8C7AE"),
self.placeholder("Backstage", "demo-gallery-backstage.jpg", "#A4513B"),
self.placeholder("In scena", "demo-gallery-show.jpg", "#515D53"),
self.placeholder("Il gruppo", "demo-gallery-group.jpg", "#4A433A"),
]
homepage = HomePage.objects.first()
if homepage is None:
homepage = HomePage(
title="Home",
slug="laboratorio",
hero_title="Il teatro diventa presenza.",
hero_subtitle=(
"Un laboratorio dove corpo, voce, ascolto e relazione "
"diventano scena."
),
)
Page.get_first_root_node().add_child(instance=homepage)
homepage.hero_title = "Il teatro diventa presenza."
homepage.hero_subtitle = (
"Un laboratorio dove corpo, voce, ascolto e relazione diventano scena."
)
homepage.hero_image = hero_image
homepage.intro_title = "Uno spazio per esserci davvero"
homepage.intro_body = (
"<p>Ogni incontro è uno spazio di pratica: si prova, si sbaglia, "
"si ascolta, si ricomincia. Il gruppo diventa materia viva, la scena "
"diventa occasione di scoperta.</p>"
)
homepage.cta_primary_label = "Vieni a conoscerci"
homepage.cta_primary_url = "#contatti"
homepage.cta_secondary_label = "Guarda la galleria"
homepage.cta_secondary_url = "#galleria"
homepage.laboratory_title = "Il laboratorio"
homepage.laboratory_body = (
"<p>Corpo, voce e improvvisazione sono strumenti per allenare "
"l'ascolto, la relazione e una presenza scenica autentica.</p>"
)
homepage.laboratory_image = laboratory_image
homepage.save_revision().publish()
homepage.feature_cards.all().delete()
cards = [
(
"Per chi inizia",
"Non serve esperienza: servono curiosità e voglia di mettersi in gioco.",
),
(
"Per chi vuole crescere",
"Una pratica costante per conoscere meglio corpo, voce e presenza.",
),
(
"Per chi ama il gruppo",
"La scena nasce dall'ascolto e dalla fiducia costruita insieme.",
),
]
for order, (title, text) in enumerate(cards):
homepage.feature_cards.create(title=title, text=text, sort_order=order)
homepage.save_revision().publish()
site = Site.objects.filter(is_default_site=True).first()
if site is None:
site = Site.objects.create(
hostname="localhost",
port=8000,
site_name="Laboratorio Teatrale",
root_page=homepage,
is_default_site=True,
)
elif site.root_page_id != homepage.id:
site.root_page = homepage
site.site_name = "Laboratorio Teatrale"
site.save(update_fields=["root_page", "site_name"])
settings, _ = SiteSettings.objects.get_or_create(site=site)
settings.laboratory_name = "Laboratorio Teatrale"
settings.short_claim = "Il teatro diventa presenza."
settings.email = "ciao@laboratorioteatrale.it"
settings.phone = "+39 333 123 4567"
settings.whatsapp = "+39 333 123 4567"
settings.instagram = "https://www.instagram.com/"
settings.facebook = "https://www.facebook.com/"
settings.address = "Via del Teatro 12, Roma"
settings.footer_text = "Uno spazio di ricerca, ascolto e presenza."
settings.save()
TeacherProfile.objects.update_or_create(
name="Andrea Rossi",
defaults={
"photo": teacher_image,
"short_bio": (
"Attore, regista e formatore. Accompagna gruppi e persone "
"nella ricerca di una presenza scenica sincera."
),
"full_bio": (
"<p>Da oltre quindici anni lavora tra formazione, creazione "
"collettiva e spettacolo dal vivo.</p>"
),
"quote": "Il teatro non è fingere: è imparare a essere presenti.",
},
)
LessonInfo.objects.update_or_create(
day_time="Ogni mercoledì, 19:3022:00",
defaults={
"location": "Spazio Teatro, Via del Teatro 12, Roma",
"audience": "Adulti, con o senza esperienza precedente.",
"description": (
"<p>Training fisico e vocale, improvvisazione, ascolto, "
"composizione e lavoro sulla scena.</p>"
),
"trial_lesson": "La prima lezione di prova è gratuita su prenotazione.",
"notes": "Abbigliamento comodo consigliato.",
},
)
Show.objects.update_or_create(
title="Tracce",
year=2025,
defaults={
"short_description": (
"Un lavoro corale sulle storie che lasciamo e che ci attraversano."
),
"description": (
"<p>Esito scenico nato dalle improvvisazioni e dalle scritture "
"del gruppo.</p>"
),
"poster": show_image,
"location": "Teatro di Quartiere",
"cast": "Allieve e allievi del laboratorio",
"order": 0,
"visible_on_home": True,
},
)
Show.objects.update_or_create(
title="Sottovoce",
year=2024,
defaults={
"short_description": (
"Un attraversamento delicato delle parole che restano inascoltate."
),
"description": (
"<p>Un progetto costruito attraverso voce, silenzio e movimento.</p>"
),
"poster": second_show_image,
"location": "Spazio Teatro",
"cast": "Laboratorio annuale",
"order": 1,
"visible_on_home": True,
},
)
gallery_entries = [
(GalleryItem.Category.LESSONS, "Ascolto e movimento"),
(GalleryItem.Category.BACKSTAGE, "Prima dello spettacolo"),
(GalleryItem.Category.SHOWS, "Una scena di Tracce"),
(GalleryItem.Category.GROUP, "Il laboratorio, insieme"),
]
for order, (image, (category, caption)) in enumerate(
zip(gallery_images, gallery_entries, strict=True)
):
GalleryItem.objects.update_or_create(
image=image,
defaults={
"category": category,
"caption": caption,
"order": order,
"visible_on_home": True,
},
)
self.stdout.write(self.style.SUCCESS("Demo content is ready."))