[Django] 13 - Parent and Child Class of Wagtail
Ref: Wagtail CMS: How to subclass Wagtail Pages
使用继承 ORM
一、 继承 - Create new ORM
[ blog/models.py ]
疑问,是否也同时继承了 InlinePanel 的部分?有的!
# First subclassed blog post page class ArticleBlogPage(BlogDetailPage): """A subclassed blog post page for articles.""" template = "blog/article_blog_page.html" subtitle = models.CharField( max_length=100, blank=True, null=True ) intro_image = models.ForeignKey( "wagtailimages.Image", blank=True, null=True, on_delete=models.SET_NULL, help_text='Best size for this image will be 1400x400' )
----------------------------------------------------------------------------- content_panels = Page.content_panels + [ FieldPanel("custom_title"), FieldPanel("subtitle"), ImageChooserPanel("banner_image"), ImageChooserPanel("intro_image"), MultiFieldPanel( [ InlinePanel("blog_authors", label="Author", min_num=1, max_num=4) ], heading="Author(s)" ), MultiFieldPanel( [ FieldPanel("categories", widget=forms.CheckboxSelectMultiple) ], heading="Categories" ), StreamFieldPanel("content"), ]
class VideoBlogPage(BlogDetailPage)
# Second subclassed page class VideoBlogPage(BlogDetailPage): """A video subclassed page.""" template = "blog/video_blog_page.html" youtube_video_id = models.CharField(max_length=30) content_panels = Page.content_panels + [ FieldPanel("custom_title"), ImageChooserPanel("banner_image"), MultiFieldPanel( [ InlinePanel("blog_authors", label="Author", min_num=1, max_num=4) ], heading="Author(s)" ), MultiFieldPanel( [ FieldPanel("categories", widget=forms.CheckboxSelectMultiple) ], heading="Categories" ), FieldPanel("youtube_video_id"), StreamFieldPanel("content"), ]
二、Template 分析
article 主题效果:
-
- 标题
- 类别
- 作者
- 图片
- 文字
[1] <img> 标签的alt 属性指定了替代文本,用于在图像无法显示或者用户禁用图像显示时,代替图像显示在浏览器中的内容。
[2] 标题的 logic,参见 [Django] 08 - StreamField of Wagtail。
{% extends "base.html" %} {% load wagtailimages_tags wagtailcore_tags %} {% block content %}
# 比例 # {% image self.banner_image fill-1200x300 as banner %} <img src="{{ banner.url }}" alt="{{ banner.alt }}" style='width: 100%; height: auto;'> <div class="container mt-5 mb-5"> <div class="text-center"> <h1> {% if self.custom_title %} {{ self.custom_title }} {% else %} {{ self.title }} {% endif %} </h1> {% if self.subtitle %} <h3>{{ self.subtitle }}</h3> {% endif %}
{% if self.categories.count %} <div style="padding: 0 20px 20px"> {% for cat in self.categories.all %} <a href="?category={{ cat.slug }}"> {{ cat.name }} </a>{% if not forloop.last %}, {% endif %} # 有可能是多个类别,最后item后不跟"逗号"的小技巧写法 {% endfor %} </div> {% endif %}
<div class="d-flex justify-content-center"> {% for iter in self.blog_authors.all %} {% image iter.author.image fill-50x50 as img %} <div> <img src="{{ img.url }}" class="rounded-circle" alt="{{ iter.author.name }}"> </div> {% if iter.author.website %} <a href="{{ iter.author.website }}"> {{ iter.author.name }} </a> {% else %} {{ iter.author.name }} # 有链接就写链接,没有就直接上文本 {% endif %} </div> {% endfor %} </div> </div> </div> {% if self.intro_image %} <div class="container"> <div class="row"> <div class="col-lg-8 offset-lg-2"> {% image self.intro_image fill-1400x400 as intro_img %} <img src="{{ intro_img.url }}" alt="{{ intro_img.alt }}"> </div> </div> </div> {% endif %} <div class="container"> <div class="row"> <div class="col-lg-8 offset-lg-2"> {% for block in self.content %} {% include_block block %} {% endfor %} </div> </div> </div>
{% endblock %}
继承特性
一、自动加载 wagtail package
(wagtail) jeffrey@unsw-ThinkPad-T490:mysite$ python manage.py shell_plus --ipython # Shell Plus Model Imports from blog.models import ArticleBlogPage, BlogAuthor, BlogAuthorsOrderable, BlogCategory, BlogDetailPage, BlogListingPage, VideoBlogPage from django.contrib.admin.models import LogEntry from django.contrib.auth.models import Group, Permission, User from django.contrib.contenttypes.models import ContentType from django.contrib.sessions.models import Session from flex.models import FlexPage from home.models import HomePage, HomePageCarouselImages from mobilar.models import MobilarListingPage, MobilarPage from site_settings.models import SocialMediaSettings from subscribers.models import Subscribers from taggit.models import Tag, TaggedItem from wagtail.contrib.forms.models import FormSubmission from wagtail.contrib.redirects.models import Redirect from wagtail.core.models import Collection, CollectionViewRestriction, GroupCollectionPermission, GroupPagePermission, Page, PageRevision, PageViewRestriction, Site from wagtail.documents.models import Document from wagtail.embeds.models import Embed from wagtail.images.models import Image, Rendition from wagtail.search.models import Query, QueryDailyHits from wagtail.users.models import UserProfile # Shell Plus Django Imports from django.core.cache import cache from django.conf import settings from django.contrib.auth import get_user_model from django.db import transaction from django.db.models import Avg, Case, Count, F, Max, Min, Prefetch, Q, Sum, When from django.utils import timezone from django.urls import reverse from django.db.models import Exists, OuterRef, Subquery Python 3.7.5 (default, Nov 7 2019, 10:50:52) Type 'copyright', 'credits' or 'license' for more information IPython 7.19.0 -- An enhanced Interactive Python. Type '?' for help.
-
识别 父类 or 子类
In [1]: posts = BlogDetailPage.objects.all() In [2]: posts Out[2]: <PageQuerySet [<BlogDetailPage: Blog Title for Blog detail page>, <BlogDetailPage: Blog Title for Blog detail page 2>, <BlogDetailPage: Blog Title for Blog detail page 3>, <BlogDetailPage: new article>]>
# 显示父类 In [3]: posts = BlogDetailPage.objects.live().exact_type(BlogDetailPage) In [4]: posts Out[4]: <PageQuerySet [<BlogDetailPage: Blog Title for Blog detail page>, <BlogDetailPage: Blog Title for Blog detail page 2>, <BlogDetailPage: Blog Title for Blog detail page 3>]>
# 显示子类 In [5]: posts = BlogDetailPage.objects.live().not_exact_type(BlogDetailPage) In [6]: posts Out[6]: <PageQuerySet [<BlogDetailPage: new article>]>
但,类的名字似乎没有对应的变化,不是很友好。
-
显示 子类的 具体信息
体现了 .specific 的作用。
In [2]: articles = BlogDetailPage.objects.live().exact_type(ArticleBlogPage) In [3]: articles Out[3]: <PageQuerySet [<BlogDetailPage: new article>]>
In [4]: articles = BlogDetailPage.objects.live().exact_type(ArticleBlogPage).specific(defer=False) In [5]: articles Out[5]: <PageQuerySet [<ArticleBlogPage: new article>]>
End.