diff --git a/README.md b/README.md index d90b5b1..0ed9a13 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,8 @@ Website for Python Ireland (python.ie / pycon.ie) community, built with Django 6 4. Generate sample data (creates pages, navigation, meetups): ```bash - docker compose run --rm web python pythonie/manage.py generate_sample_data --settings=pythonie.settings.dev + task django:generate-sample-data + # or: docker compose run --rm web python pythonie/manage.py generate_sample_data --settings=pythonie.settings.dev ``` 5. Create a superuser: @@ -58,7 +59,7 @@ If you prefer to develop without Docker: 5. Activate the virtualenv: `source pythonie-venv/bin/activate` 6. Install dependencies: `pip install -r requirements.txt` (or `uv pip install -r requirements.txt`) 7. Set up the database: `python pythonie/manage.py migrate --settings=pythonie.settings.dev` -8. Generate sample data: `python pythonie/manage.py generate_sample_data --settings=pythonie.settings.dev` +8. Generate sample data: `task django:generate-sample-data` (or `python pythonie/manage.py generate_sample_data --settings=pythonie.settings.dev`) 9. Create a superuser: `python pythonie/manage.py createsuperuser --settings=pythonie.settings.dev` 10. Install and run Redis server locally: `redis-server` 11. Set Redis environment variable: `export REDISCLOUD_URL=127.0.0.1:6379` @@ -95,7 +96,7 @@ task django:make-migrations # Create new migrations task django:collect-static # Collect static files # Sample Data (for development) -python pythonie/manage.py generate_sample_data --settings=pythonie.settings.dev +task django:generate-sample-data # Testing task tests # Run test suite diff --git a/Taskfile.yaml b/Taskfile.yaml index 09a68eb..be24ecb 100644 --- a/Taskfile.yaml +++ b/Taskfile.yaml @@ -145,6 +145,16 @@ tasks: cmds: - docker compose run --rm web python pythonie/manage.py collectstatic + django:generate-sample-data: + desc: Generate sample data for development + cmds: + - | + if command -v docker >/dev/null 2>&1 && docker ps >/dev/null 2>&1; then + docker compose run --rm web python pythonie/manage.py generate_sample_data + else + python pythonie/manage.py generate_sample_data --settings=pythonie.settings.dev + fi + dependencies:compute: desc: Compute the dependencies cmds: diff --git a/development.env b/development.env new file mode 100644 index 0000000..94ad002 --- /dev/null +++ b/development.env @@ -0,0 +1,7 @@ +DJANGO_SETTINGS_MODULE=pythonie.settings.dev +PGDATABASE=pythonie +PGUSER=postgres +PGPASSWORD=pythonie +PGHOST=postgres +REDISCLOUD_URL=redis://redis:6379 + diff --git a/pythonie/core/factories.py b/pythonie/core/factories.py index 1ae74f1..d1b5112 100644 --- a/pythonie/core/factories.py +++ b/pythonie/core/factories.py @@ -1,38 +1,49 @@ -import factory from django.utils import timezone -from factory.django import DjangoModelFactory -from meetups.models import Meetup -from sponsors.models import SponsorshipLevel +import wagtail_factories from core.models import HomePage, SimplePage +from meetups.models import Meetup +from sponsors.models import SponsorshipLevel -class SponsorshipLevelFactory(DjangoModelFactory): - class Meta: - model = SponsorshipLevel - django_get_or_create = ("name",) +def create_sponsorship_level(name="Bronze", level=100): + return SponsorshipLevel.objects.get_or_create(name=name, defaults={"level": level})[ + 0 + ] - level = 100 - name = "Bronze" +def create_meetup( + id, + name="Python Ireland Meetup", + description="Monthly Python meetup in Dublin", + event_url="https://meetup.com/pythonireland/", + time=None, + created=None, + rsvps=50, + status="upcoming", + visibility="public", +): + if time is None: + time = timezone.now() + timezone.timedelta(days=30) + if created is None: + created = timezone.now() -class MeetupFactory(DjangoModelFactory): - class Meta: - model = Meetup - django_get_or_create = ("id",) + return Meetup.objects.get_or_create( + id=id, + defaults={ + "name": name, + "description": description, + "event_url": event_url, + "time": time, + "created": created, + "rsvps": rsvps, + "status": status, + "visibility": visibility, + }, + )[0] - id = factory.Sequence(lambda n: f"meetup-{n}") - name = "Python Ireland Meetup" - description = "Monthly Python meetup in Dublin" - event_url = "https://meetup.com/pythonireland/" - time = factory.LazyFunction(lambda: timezone.now() + timezone.timedelta(days=30)) - created = factory.LazyFunction(timezone.now) - rsvps = 50 - status = "upcoming" - visibility = "public" - -class HomePageFactory(DjangoModelFactory): +class HomePageFactory(wagtail_factories.PageFactory): class Meta: model = HomePage @@ -42,10 +53,18 @@ class Meta: body = [] -class SimplePageFactory(DjangoModelFactory): +class SimplePageFactory(wagtail_factories.PageFactory): class Meta: model = SimplePage title = "Sample Page" slug = "sample-page" body = [] + + +def SponsorshipLevelFactory(name="Bronze", level=100): + return create_sponsorship_level(name=name, level=level) + + +def MeetupFactory(id, name="Python Ireland Meetup", **kwargs): + return create_meetup(id=id, name=name, **kwargs) diff --git a/pythonie/core/management/commands/generate_sample_data.py b/pythonie/core/management/commands/generate_sample_data.py index 905ad6e..a8c32fd 100644 --- a/pythonie/core/management/commands/generate_sample_data.py +++ b/pythonie/core/management/commands/generate_sample_data.py @@ -41,23 +41,47 @@ def _create_home_page(self): self.stdout.write("Home page already exists") return home - wagtail_root = Page.objects.get(depth=1) + try: + wagtail_root = Page.objects.get(depth=1) + except Page.DoesNotExist: + from wagtail.models import Locale + + locale, _ = Locale.objects.get_or_create(language_code="en") + wagtail_root = Page.add_root( + instance=Page(title="Root", slug="root", locale=locale) + ) + self.stdout.write("Created Wagtail root page") + default_home_exists = Page.objects.filter(slug="home", depth=2).exists() slug = "python-ireland" if default_home_exists else "home" - home = HomePageFactory.build( + home = HomePageFactory( + parent=wagtail_root, slug=slug, show_in_menus=True, body=self._get_home_content(), ) - wagtail_root.add_child(instance=home) - self.stdout.write(self.style.SUCCESS("Created home page")) - - site = Site.objects.filter(is_default_site=True).first() - if site: + # Publish the home page + revision = home.save_revision() + revision.publish() + self.stdout.write(self.style.SUCCESS("Created and published home page")) + + # Create or update the default site + site, created = Site.objects.get_or_create( + is_default_site=True, + defaults={ + "hostname": "localhost", + "port": 8000, + "site_name": "Python Ireland", + "root_page": home, + }, + ) + if not created: site.root_page = home site.save() self.stdout.write(self.style.SUCCESS("Updated site root page")) + else: + self.stdout.write(self.style.SUCCESS("Created default site")) return home @@ -88,10 +112,13 @@ def _create_page(self, parent, title, slug, body=None): self.stdout.write(f" {title} already exists") return SimplePage.objects.get(slug=slug) - page = SimplePageFactory.build( - title=title, slug=slug, body=body or [], show_in_menus=True + page = SimplePageFactory( + parent=parent, + title=title, + slug=slug, + body=body or [], + show_in_menus=True, ) - parent.add_child(instance=page) self.stdout.write(self.style.SUCCESS(f"Created {title}")) return page diff --git a/requirements/dev.in b/requirements/dev.in index 7c25737..309dd5f 100644 --- a/requirements/dev.in +++ b/requirements/dev.in @@ -2,7 +2,7 @@ -c main.txt coverage django-debug-toolbar -factory-boy +wagtail-factories fakeredis isort model_mommy