from django.db import models from modelcluster.contrib.taggit import ClusterTaggableManager from modelcluster.fields import ParentalKey from taggit.models import TaggedItemBase from wagtail.admin.panels import FieldPanel from wagtail.fields import StreamField from wagtail.search import index from apps.core.blocks import COMMON_BLOCKS from apps.core.models import SEOablePage class BlogIndexPage(SEOablePage): """博客列表页,本身不直接管理内容,子页面为 BlogPage。""" intro = models.TextField(blank=True, verbose_name="栏目简介") content_panels = SEOablePage.content_panels + [ FieldPanel("intro"), ] subpage_types = ["blog.BlogPage"] parent_page_types = ["home.HomePage"] class Meta: verbose_name = "博客栏目页" def get_context(self, request, *args, **kwargs): context = super().get_context(request, *args, **kwargs) context["posts"] = ( BlogPage.objects.live().descendant_of(self).order_by("-published_at") ) return context class BlogPageTag(TaggedItemBase): content_object = ParentalKey( "BlogPage", related_name="tagged_items", on_delete=models.CASCADE ) class BlogPage(SEOablePage): """技术博客文章页。""" published_at = models.DateTimeField(verbose_name="发布时间") intro = models.CharField(max_length=250, blank=True, verbose_name="摘要") cover_image = models.ForeignKey( "wagtailimages.Image", null=True, blank=True, on_delete=models.SET_NULL, related_name="+", verbose_name="封面图", ) body = StreamField(COMMON_BLOCKS, use_json_field=True, blank=True) tags = ClusterTaggableManager(through=BlogPageTag, blank=True, verbose_name="标签") search_fields = SEOablePage.search_fields + [ index.SearchField("intro"), index.SearchField("body"), ] content_panels = SEOablePage.content_panels + [ FieldPanel("published_at"), FieldPanel("intro"), FieldPanel("cover_image"), FieldPanel("body"), FieldPanel("tags"), ] parent_page_types = ["blog.BlogIndexPage"] subpage_types = [] class Meta: verbose_name = "博客文章"