[Django] 12 - Snippets of Wagtail

snippet is a small section of text or source code that can be inserted into the code of a program or Web page. Snippets provide an easy way to implement commonly used code or functions into a larger section of code.

就是可复用的代码。

 

Option 定义与使用分离 

一、注册以设置选项

注册 snippet,看来是系统内置的,wagtail.snippets.models直接有提供。

就是在这里定义了需要的 options:有哪些作者可以选择。

from wagtail.snippets.models import register_snippet


#
# 与 blog/admin.py, blog/models.py 不同  
# 前者是继承的 ModelAdmin, 
# 这里是继承的 model.Model
#
class BlogAuthor(models.Model):
    """Blog author for snippets."""

    name    = models.CharField(max_length=100)
    website = models.URLField(blank=True, null=True)
    image   = models.ForeignKey(
        "wagtailimages.Image",
        on_delete=models.SET_NULL,
        null=True,
        blank=False,
        related_name="+",
    )

    panels = [
        MultiFieldPanel(
            [
                FieldPanel("name"),
                ImageChooserPanel("image"),
            ],
            heading="Name and Image",
        ),
        MultiFieldPanel(
            [
                FieldPanel("website"),
            ],
            heading="Links"
        )
    ]

    def __str__(self):
        """String repr of this class."""
        return self.name

    class Meta:  # noqa
        verbose_name        = "Blog Author"
        verbose_name_plural = "Blog Authors"


register_snippet(BlogAuthor)

 

二、设置选项的容器

也就是 使用这些选项值的子控件。

作者栏,可以作为一个独立的表,也可以被多个板块引用。

 

  • 子控件与选项建立联系

如何联系到 之前的 options?

(1) 类似homepage的“图片栏”,作为了blog page的InlinePanel。

(2) 通过数据库中的表名的规则,引用到 作者栏的options。(option定义与使用的分离)

class BlogAuthorsOrderable(Orderable):
    """This allows us to select one or more blog authors from Snippets."""

    # (1) 因为是 InlinePanel,所以 依附的父表在这里要指定出来
    page = ParentalKey("blog.BlogDetailPage", related_name="blog_authors")

    author = models.ForeignKey(
        "blog.BlogAuthor",  # (2) 这里代表了数据库中的一个表,而表是与类的名字挂钩
        on_delete=models.CASCADE,
    )

    panels = [
        SnippetChooserPanel("author"),
    ]

 

 

Option 定义与使用在一起

一、注册以设置选项

class BlogCategory(models.Model):
    """Blog catgory for a snippet."""

    name = models.CharField(max_length=255)
    slug = models.SlugField(
        verbose_name="slug",
        allow_unicode=True,
        max_length=255,
        help_text='A slug to identify posts by this category',
    )

    panels = [
        FieldPanel("name"),
        FieldPanel("slug"),
    ]

    class Meta:
        verbose_name = "Blog Category"
        verbose_name_plural = "Blog Categories"
        ordering = ["name"]

    def __str__(self):
        return self.name


register_snippet(BlogCategory)

 

二、设置选项的容器  

看成是,有点特殊的 控件,因为控件的值 需要另外设置。

其实就是直接读取数据库的表:BlogCategory,以获取options。

 

  • 子控件与选项建立联系

 通过表名的规则去建立联系。

from modelcluster.fields import ParentalKey, ParentalManyToManyField

# part 2 blog_image = models.ForeignKey(   "wagtailimages.Image",   blank=False,   null=True,   related_name="+",   on_delete=models.SET_NULL, ) # part 3 categories = ParentalManyToManyField(   "blog.BlogCategory", # 通过orm定义 对应的数据库的表   blank=True, # 表示 可以不选,空着 )

 

 

集成到控制台

一、两者的区别

第一个是 orderable,类似 homepage的图片栏,子选项是动态、不定的。

第二个就是个普通的控件,但控件的value需要设置,也就是对应的orm中需要有数据。

    # Integration.
    content_panels = Page.content_panels + [
        FieldPanel("custom_title"),
        ImageChooserPanel("blog_image"),
        MultiFieldPanel(
            [
                # 因为是 InlinePanel,所以通过 blog_authors 去定位。
                InlinePanel("blog_authors", label="Author", min_num=1, max_num=2)
            ],
            heading="Author(s)"
        ),
        MultiFieldPanel(
            [
                FieldPanel("categories", widget=forms.CheckboxSelectMultiple)  # forms中的多选控件
            ],
            heading="Categories"
        ),
        StreamFieldPanel("content"),
    ]

 

  地图也是新子模块,如果是集成地图,怎么办?

 

End.

posted @ 2020-12-28 18:32  郝壹贰叁  阅读(181)  评论(0编辑  收藏  举报