From 33e042ed05a07af2bf75fdf09bf0801c3bb5a919 Mon Sep 17 00:00:00 2001 From: Saurabh Shelar Date: Fri, 23 Jan 2026 21:09:05 +0000 Subject: [PATCH 1/2] =?UTF-8?q?=E2=9C=A8=20feat:=20add=20development=20env?= =?UTF-8?q?ironment=20configuration=20and=20update=20sample=20data=20gener?= =?UTF-8?q?ation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 7 +- Taskfile.yaml | 10 +++ development.env | 7 ++ pythonie/core/factories.py | 72 ++++++++++--------- .../commands/generate_sample_data.py | 46 +++++++++--- requirements/dev.in | 2 +- 6 files changed, 98 insertions(+), 46 deletions(-) create mode 100644 development.env 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..93f28a9 100644 --- a/pythonie/core/factories.py +++ b/pythonie/core/factories.py @@ -1,38 +1,38 @@ -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",) - - level = 100 - name = "Bronze" - - -class MeetupFactory(DjangoModelFactory): - class Meta: - model = Meetup - django_get_or_create = ("id",) - - 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): +def create_sponsorship_level(name="Bronze", level=100): + return SponsorshipLevel.objects.get_or_create(name=name, defaults={"level": level})[0] + + +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() + + 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] + + +class HomePageFactory(wagtail_factories.PageFactory): class Meta: model = HomePage @@ -42,10 +42,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..94c7388 100644 --- a/pythonie/core/management/commands/generate_sample_data.py +++ b/pythonie/core/management/commands/generate_sample_data.py @@ -41,23 +41,46 @@ 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 +111,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 From 7374b5bc936cd46ea3d7b08254722617c330ee91 Mon Sep 17 00:00:00 2001 From: Saurabh Shelar Date: Fri, 23 Jan 2026 21:24:13 +0000 Subject: [PATCH 2/2] style: format code with ruff --- pythonie/core/factories.py | 23 ++++++++++++++----- .../commands/generate_sample_data.py | 3 ++- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/pythonie/core/factories.py b/pythonie/core/factories.py index 93f28a9..d1b5112 100644 --- a/pythonie/core/factories.py +++ b/pythonie/core/factories.py @@ -5,18 +5,29 @@ from meetups.models import Meetup from sponsors.models import SponsorshipLevel + def create_sponsorship_level(name="Bronze", level=100): - return SponsorshipLevel.objects.get_or_create(name=name, defaults={"level": level})[0] + return SponsorshipLevel.objects.get_or_create(name=name, defaults={"level": level})[ + 0 + ] -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"): +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() - + return Meetup.objects.get_or_create( id=id, defaults={ @@ -28,7 +39,7 @@ def create_meetup(id, name="Python Ireland Meetup", description="Monthly Python "rsvps": rsvps, "status": status, "visibility": visibility, - } + }, )[0] diff --git a/pythonie/core/management/commands/generate_sample_data.py b/pythonie/core/management/commands/generate_sample_data.py index 94c7388..a8c32fd 100644 --- a/pythonie/core/management/commands/generate_sample_data.py +++ b/pythonie/core/management/commands/generate_sample_data.py @@ -45,6 +45,7 @@ def _create_home_page(self): 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) @@ -73,7 +74,7 @@ def _create_home_page(self): "port": 8000, "site_name": "Python Ireland", "root_page": home, - } + }, ) if not created: site.root_page = home