Skip to content

Commit ed36433

Browse files
committed
feat: cms app Site, Page, Section admin 기능 추가
1 parent c49d579 commit ed36433

3 files changed

Lines changed: 84 additions & 5 deletions

File tree

app/cms/admin.py

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,69 @@
1+
from cms.admin_mixins import RelatedReadonlyFieldsMixin
12
from cms.models import Page, Section, Sitemap
23
from django.contrib import admin
34

45

5-
class SitemapAdmin(admin.ModelAdmin):
6-
pass
6+
class SitemapAdmin(RelatedReadonlyFieldsMixin, admin.ModelAdmin):
7+
fields = ["id", "parent_sitemap", "page", "name", "order", "display_start_at", "display_end_at"]
8+
readonly_fields = ["id"]
9+
related_readonly_config = {
10+
"page": ["id", "is_active", "css", "title", "subtitle"],
11+
"parent_sitemap": ["id", "name", "order", "display_start_at", "display_end_at"],
12+
}
13+
14+
def get_fieldsets(self, request, obj=...):
15+
original_fieldsets = super().get_fieldsets(request, obj)
16+
if obj and obj.parent_sitemap:
17+
original_fieldsets.append(
18+
(
19+
"Parent Sitemap 정보",
20+
{
21+
"fields": [f"get_parent_sitemap_{f}" for f in self.related_readonly_config["parent_sitemap"]],
22+
"classes": ("collapse",),
23+
},
24+
)
25+
)
26+
if obj and obj.page:
27+
original_fieldsets.append(
28+
(
29+
"Page 정보",
30+
{
31+
"fields": [f"get_page_{f}" for f in self.related_readonly_config["page"]],
32+
"classes": ("collapse",),
33+
},
34+
)
35+
)
36+
return original_fieldsets
37+
38+
def get_queryset(self, request):
39+
return super().get_queryset(request).select_related("page").select_related("parent_sitemap")
740

841

942
class PageAdmin(admin.ModelAdmin):
1043
pass
1144

1245

13-
class SectionAdmin(admin.ModelAdmin):
14-
pass
46+
class SectionAdmin(RelatedReadonlyFieldsMixin, admin.ModelAdmin):
47+
fields = ["id", "page", "order", "css", "body"]
48+
readonly_fields = ["id"]
49+
related_readonly_config = {"page": ["id", "is_active", "css", "title", "subtitle"]}
50+
51+
def get_fieldsets(self, request, obj=...):
52+
original_fieldsets = super().get_fieldsets(request, obj)
53+
if obj and obj.page:
54+
original_fieldsets.append(
55+
(
56+
"Page 정보",
57+
{
58+
"fields": [f"get_page_{f}" for f in self.related_readonly_config["page"]],
59+
"classes": ("collapse",),
60+
},
61+
)
62+
)
63+
return original_fieldsets
64+
65+
def get_queryset(self, request):
66+
return super().get_queryset(request).select_related("page")
1567

1668

1769
admin.site.register(Sitemap, SitemapAdmin)

app/cms/admin_mixins.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
class RelatedReadonlyFieldsMixin:
2+
related_readonly_config = {}
3+
4+
def _generate_related_getter(self, rel, field, prefix=""):
5+
def _func(admin_self, obj):
6+
related = getattr(obj, rel)
7+
return getattr(related, field) if related else None
8+
9+
_func.short_description = f"{prefix} {field.replace('_', ' ')}"
10+
return _func
11+
12+
def _register_dynamic_readonly_fields(self):
13+
for rel, fields in self.related_readonly_config.items():
14+
for field in fields:
15+
method_name = f"get_{rel}_{field}"
16+
getter = self._generate_related_getter(rel, field, prefix=rel.capitalize())
17+
setattr(self.__class__, method_name, getter)
18+
19+
def __init__(self, *args, **kwargs):
20+
super().__init__(*args, **kwargs)
21+
self._register_dynamic_readonly_fields()
22+
23+
def get_readonly_fields(self, request, obj=None):
24+
base = super().get_readonly_fields(request, obj)
25+
generated = [f"get_{rel}_{field}" for rel, fields in self.related_readonly_config.items() for field in fields]
26+
return list(base) + generated

app/cms/models.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import uuid
22

3+
from django.core.validators import MinValueValidator
34
from django.db import models
45

56

@@ -21,7 +22,7 @@ class Sitemap(models.Model):
2122
"self", null=True, blank=True, default=None, on_delete=models.SET_NULL, related_name="children"
2223
)
2324
name = models.CharField(max_length=256)
24-
order = models.IntegerField(default=0)
25+
order = models.IntegerField(default=0, validators=MinValueValidator(0))
2526
page = models.ForeignKey(Page, on_delete=models.PROTECT)
2627
display_start_at = models.DateTimeField(null=True, blank=True)
2728
display_end_at = models.DateTimeField(null=True, blank=True)

0 commit comments

Comments
 (0)