[Django] 12 - Snippets of Wagtail
A 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.