From b3c64b01c1e3aac119c325ef4cce29a5a0faeaf5 Mon Sep 17 00:00:00 2001 From: MUsoftware Date: Sun, 18 May 2025 15:59:05 +0900 Subject: [PATCH 1/2] =?UTF-8?q?chore:=20=EB=AA=A8=EB=8D=B8=EB=93=A4?= =?UTF-8?q?=EC=97=90=20created=5Fat=20/=20updated=5Fat=20/=20deleted=5Fat?= =?UTF-8?q?=20=EB=B0=8F=20=EA=B3=B5=ED=86=B5=20QuertSet=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ..._options_alter_sitemap_options_and_more.py | 335 ++++++++++++++++++ app/cms/models.py | 41 ++- app/cms/urls.py | 4 +- app/cms/views.py | 10 +- app/core/models.py | 9 +- 5 files changed, 374 insertions(+), 25 deletions(-) create mode 100644 app/cms/migrations/0004_alter_section_options_alter_sitemap_options_and_more.py diff --git a/app/cms/migrations/0004_alter_section_options_alter_sitemap_options_and_more.py b/app/cms/migrations/0004_alter_section_options_alter_sitemap_options_and_more.py new file mode 100644 index 0000000..7a02de7 --- /dev/null +++ b/app/cms/migrations/0004_alter_section_options_alter_sitemap_options_and_more.py @@ -0,0 +1,335 @@ +# Generated by Django 5.2 on 2025-05-18 06:54 + +import django.db.models.deletion +import django.utils.timezone +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("cms", "0003_alter_historicalsitemap_order_alter_sitemap_order"), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.AlterModelOptions(name="section", options={"ordering": ["order"]}), + migrations.AlterModelOptions(name="sitemap", options={"ordering": ["order"]}), + migrations.RemoveField(model_name="historicalpage", name="is_active"), + migrations.RemoveField(model_name="page", name="is_active"), + migrations.AddField( + model_name="historicalpage", + name="created_at", + field=models.DateTimeField(blank=True, default=django.utils.timezone.now, editable=False), + preserve_default=False, + ), + migrations.AddField( + model_name="historicalpage", + name="created_by", + field=models.ForeignKey( + blank=True, + db_constraint=False, + null=True, + on_delete=django.db.models.deletion.DO_NOTHING, + related_name="+", + to=settings.AUTH_USER_MODEL, + ), + ), + migrations.AddField( + model_name="historicalpage", + name="deleted_at", + field=models.DateTimeField(blank=True, null=True), + ), + migrations.AddField( + model_name="historicalpage", + name="deleted_by", + field=models.ForeignKey( + blank=True, + db_constraint=False, + null=True, + on_delete=django.db.models.deletion.DO_NOTHING, + related_name="+", + to=settings.AUTH_USER_MODEL, + ), + ), + migrations.AddField( + model_name="historicalpage", + name="updated_at", + field=models.DateTimeField(blank=True, default=django.utils.timezone.now, editable=False), + preserve_default=False, + ), + migrations.AddField( + model_name="historicalpage", + name="updated_by", + field=models.ForeignKey( + blank=True, + db_constraint=False, + null=True, + on_delete=django.db.models.deletion.DO_NOTHING, + related_name="+", + to=settings.AUTH_USER_MODEL, + ), + ), + migrations.AddField( + model_name="historicalsection", + name="created_at", + field=models.DateTimeField(blank=True, default=django.utils.timezone.now, editable=False), + preserve_default=False, + ), + migrations.AddField( + model_name="historicalsection", + name="created_by", + field=models.ForeignKey( + blank=True, + db_constraint=False, + null=True, + on_delete=django.db.models.deletion.DO_NOTHING, + related_name="+", + to=settings.AUTH_USER_MODEL, + ), + ), + migrations.AddField( + model_name="historicalsection", + name="deleted_at", + field=models.DateTimeField(blank=True, null=True), + ), + migrations.AddField( + model_name="historicalsection", + name="deleted_by", + field=models.ForeignKey( + blank=True, + db_constraint=False, + null=True, + on_delete=django.db.models.deletion.DO_NOTHING, + related_name="+", + to=settings.AUTH_USER_MODEL, + ), + ), + migrations.AddField( + model_name="historicalsection", + name="updated_at", + field=models.DateTimeField(blank=True, default=django.utils.timezone.now, editable=False), + preserve_default=False, + ), + migrations.AddField( + model_name="historicalsection", + name="updated_by", + field=models.ForeignKey( + blank=True, + db_constraint=False, + null=True, + on_delete=django.db.models.deletion.DO_NOTHING, + related_name="+", + to=settings.AUTH_USER_MODEL, + ), + ), + migrations.AddField( + model_name="historicalsitemap", + name="created_at", + field=models.DateTimeField(blank=True, default=django.utils.timezone.now, editable=False), + preserve_default=False, + ), + migrations.AddField( + model_name="historicalsitemap", + name="created_by", + field=models.ForeignKey( + blank=True, + db_constraint=False, + null=True, + on_delete=django.db.models.deletion.DO_NOTHING, + related_name="+", + to=settings.AUTH_USER_MODEL, + ), + ), + migrations.AddField( + model_name="historicalsitemap", + name="deleted_at", + field=models.DateTimeField(blank=True, null=True), + ), + migrations.AddField( + model_name="historicalsitemap", + name="deleted_by", + field=models.ForeignKey( + blank=True, + db_constraint=False, + null=True, + on_delete=django.db.models.deletion.DO_NOTHING, + related_name="+", + to=settings.AUTH_USER_MODEL, + ), + ), + migrations.AddField( + model_name="historicalsitemap", + name="updated_at", + field=models.DateTimeField(blank=True, default=django.utils.timezone.now, editable=False), + preserve_default=False, + ), + migrations.AddField( + model_name="historicalsitemap", + name="updated_by", + field=models.ForeignKey( + blank=True, + db_constraint=False, + null=True, + on_delete=django.db.models.deletion.DO_NOTHING, + related_name="+", + to=settings.AUTH_USER_MODEL, + ), + ), + migrations.AddField( + model_name="page", + name="created_at", + field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now), + preserve_default=False, + ), + migrations.AddField( + model_name="page", + name="created_by", + field=models.ForeignKey( + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name="%(class)s_created_by", + to=settings.AUTH_USER_MODEL, + ), + ), + migrations.AddField( + model_name="page", + name="deleted_at", + field=models.DateTimeField(blank=True, null=True), + ), + migrations.AddField( + model_name="page", + name="deleted_by", + field=models.ForeignKey( + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name="%(class)s_deleted_by", + to=settings.AUTH_USER_MODEL, + ), + ), + migrations.AddField( + model_name="page", + name="updated_at", + field=models.DateTimeField(auto_now=True), + ), + migrations.AddField( + model_name="page", + name="updated_by", + field=models.ForeignKey( + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name="%(class)s_updated_by", + to=settings.AUTH_USER_MODEL, + ), + ), + migrations.AddField( + model_name="section", + name="created_at", + field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now), + preserve_default=False, + ), + migrations.AddField( + model_name="section", + name="created_by", + field=models.ForeignKey( + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name="%(class)s_created_by", + to=settings.AUTH_USER_MODEL, + ), + ), + migrations.AddField( + model_name="section", + name="deleted_at", + field=models.DateTimeField(blank=True, null=True), + ), + migrations.AddField( + model_name="section", + name="deleted_by", + field=models.ForeignKey( + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name="%(class)s_deleted_by", + to=settings.AUTH_USER_MODEL, + ), + ), + migrations.AddField( + model_name="section", + name="updated_at", + field=models.DateTimeField(auto_now=True), + ), + migrations.AddField( + model_name="section", + name="updated_by", + field=models.ForeignKey( + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name="%(class)s_updated_by", + to=settings.AUTH_USER_MODEL, + ), + ), + migrations.AddField( + model_name="sitemap", + name="created_at", + field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now), + preserve_default=False, + ), + migrations.AddField( + model_name="sitemap", + name="created_by", + field=models.ForeignKey( + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name="%(class)s_created_by", + to=settings.AUTH_USER_MODEL, + ), + ), + migrations.AddField( + model_name="sitemap", + name="deleted_at", + field=models.DateTimeField(blank=True, null=True), + ), + migrations.AddField( + model_name="sitemap", + name="deleted_by", + field=models.ForeignKey( + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name="%(class)s_deleted_by", + to=settings.AUTH_USER_MODEL, + ), + ), + migrations.AddField( + model_name="sitemap", + name="updated_at", + field=models.DateTimeField(auto_now=True), + ), + migrations.AddField( + model_name="sitemap", + name="updated_by", + field=models.ForeignKey( + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name="%(class)s_updated_by", + to=settings.AUTH_USER_MODEL, + ), + ), + migrations.AlterField( + model_name="section", + name="page", + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, related_name="sections", to="cms.page" + ), + ), + migrations.AlterField( + model_name="sitemap", + name="parent_sitemap", + field=models.ForeignKey( + default=None, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="children", + to="cms.sitemap", + ), + ), + ] diff --git a/app/cms/models.py b/app/cms/models.py index 431368c..cb6d5f4 100644 --- a/app/cms/models.py +++ b/app/cms/models.py @@ -1,44 +1,59 @@ -import uuid +import datetime +import typing +from core.models import BaseAbstractModel, BaseAbstractModelQuerySet from django.core.validators import MinValueValidator from django.db import models -class Page(models.Model): - id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) - is_active = models.BooleanField(default=False) +class Page(BaseAbstractModel): css = models.TextField(null=True, blank=True, default=None) title = models.CharField(max_length=256) subtitle = models.CharField(max_length=512) - # history = HistoricalRecords() def __str__(self): return str(self.title) -class Sitemap(models.Model): - id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) +class SitemapQuerySet(BaseAbstractModelQuerySet): + def filter_by_today(self) -> typing.Self: + today = datetime.date.today() + return self.filter( + models.Q(display_start_at__isnull=True) | models.Q(display_start_at__lte=today), + models.Q(display_end_at__isnull=True) | models.Q(display_end_at__gte=today), + ) + + +class Sitemap(BaseAbstractModel): parent_sitemap = models.ForeignKey( - "self", null=True, blank=True, default=None, on_delete=models.SET_NULL, related_name="children" + "self", null=True, default=None, on_delete=models.SET_NULL, related_name="children" ) + name = models.CharField(max_length=256) order = models.IntegerField(default=0, validators=[MinValueValidator(0)]) page = models.ForeignKey(Page, on_delete=models.PROTECT) + display_start_at = models.DateTimeField(null=True, blank=True) display_end_at = models.DateTimeField(null=True, blank=True) - # history = HistoricalRecords() + + objects: SitemapQuerySet = SitemapQuerySet.as_manager() + + class Meta: + ordering = ["order"] def __str__(self): return str(self.name) -class Section(models.Model): - id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) - page = models.ForeignKey(Page, on_delete=models.CASCADE) +class Section(BaseAbstractModel): + page = models.ForeignKey(Page, on_delete=models.CASCADE, related_name="sections") order = models.IntegerField(default=0) + css = models.TextField(null=True, blank=True, default=None) body = models.TextField(help_text="Content of the page, Written in markdown format") - # history = HistoricalRecords() + + class Meta: + ordering = ["order"] def __str__(self): return f"Section {self.order} of {self.page}" diff --git a/app/cms/urls.py b/app/cms/urls.py index 08930ac..878e6ca 100644 --- a/app/cms/urls.py +++ b/app/cms/urls.py @@ -20,7 +20,7 @@ from rest_framework import routers cms_router = routers.SimpleRouter() -cms_router.register("sitemap", views.SitemapListRetrieveViewSet, basename="cms-sitemap") -cms_router.register("page", views.PageListRetrieveViewSet, basename="cms-page") +cms_router.register("sitemap", views.SitemapViewSet, basename="cms-sitemap") +cms_router.register("page", views.PageViewSet, basename="cms-page") urlpatterns = [path("", include(cms_router.urls))] diff --git a/app/cms/views.py b/app/cms/views.py index c48956a..f7cd7a6 100644 --- a/app/cms/views.py +++ b/app/cms/views.py @@ -1,13 +1,13 @@ from cms.models import Page, Sitemap from cms.serializers import PageSerializer, SitemapSerializer -from rest_framework.viewsets import ReadOnlyModelViewSet +from rest_framework import mixins, viewsets -class SitemapListRetrieveViewSet(ReadOnlyModelViewSet): +class SitemapViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): serializer_class = SitemapSerializer - queryset = Sitemap.objects.all() + queryset = Sitemap.objects.filter_active().filter_by_today() -class PageListRetrieveViewSet(ReadOnlyModelViewSet): +class PageViewSet(mixins.RetrieveModelMixin, viewsets.GenericViewSet): serializer_class = PageSerializer - queryset = Page.objects.all() + queryset = Page.objects.filter_active().prefetch_related("sections") diff --git a/app/core/models.py b/app/core/models.py index 7676c5e..cb834a1 100644 --- a/app/core/models.py +++ b/app/core/models.py @@ -1,5 +1,4 @@ import collections.abc -import datetime import typing import uuid @@ -25,11 +24,11 @@ def filter_active(self) -> typing.Self: class BaseAbstractModel(models.Model): - id = models.UUIDField[uuid.UUID, uuid.UUID](primary_key=True, default=uuid.uuid4, editable=False) + id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) - created_at = models.DateTimeField[datetime.datetime, datetime.datetime](auto_now_add=True) - updated_at = models.DateTimeField[datetime.datetime, datetime.datetime](auto_now=True) - deleted_at = models.DateTimeField[datetime.datetime, datetime.datetime](null=True, blank=True) + created_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(auto_now=True) + deleted_at = models.DateTimeField(null=True, blank=True) created_by = models.ForeignKey["UserExt", "UserExt"]( User, on_delete=models.PROTECT, null=True, related_name="%(class)s_created_by" From 776850c4e432189f3526e718bbf7dc14fec5cd6c Mon Sep 17 00:00:00 2001 From: MUsoftware Date: Sun, 18 May 2025 16:07:55 +0900 Subject: [PATCH 2/2] =?UTF-8?q?flx:=20datetime=20=ED=95=84=EB=93=9C?= =?UTF-8?q?=EB=A5=BC=20date=EB=A1=9C=20=EB=B9=84=EA=B5=90=ED=95=98?= =?UTF-8?q?=EB=A0=A4=20=ED=95=98=EB=8A=94=20=EB=AC=B8=EC=A0=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/cms/models.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/cms/models.py b/app/cms/models.py index cb6d5f4..b7ce393 100644 --- a/app/cms/models.py +++ b/app/cms/models.py @@ -17,10 +17,10 @@ def __str__(self): class SitemapQuerySet(BaseAbstractModelQuerySet): def filter_by_today(self) -> typing.Self: - today = datetime.date.today() + now = datetime.datetime.now() return self.filter( - models.Q(display_start_at__isnull=True) | models.Q(display_start_at__lte=today), - models.Q(display_end_at__isnull=True) | models.Q(display_end_at__gte=today), + models.Q(display_start_at__isnull=True) | models.Q(display_start_at__lte=now), + models.Q(display_end_at__isnull=True) | models.Q(display_end_at__gte=now), )