Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1from django.db import models
2from django.template.loader import render_to_string
3from modelcluster.fields import ParentalKey
4from wagtail.admin.edit_handlers import FieldPanel, InlinePanel, StreamFieldPanel
5from wagtail.core import blocks
6from wagtail.core.fields import RichTextField, StreamField
7from wagtail.core.models import Orderable, Page
8from wagtail.images.blocks import ImageChooserBlock
9from wagtail.images.edit_handlers import ImageChooserPanel
10from wagtail.search import index
11from wagtail.contrib.table_block.blocks import TableBlock
14def generate_toc_tree(slug):
15 """
16 Generate a _toc.html template on ManualPage and
17 ManualIndexPage save to avoid full page tree rendering
18 on every page load
19 """
20 toc_tree, created = TocTree.objects.get_or_create(slug=slug)
21 toc_tree.html = render_to_string("pages/_toc.html", {},)
22 toc_tree.save()
25class TocTree(models.Model):
26 html = models.TextField(blank=True, null=True)
27 slug = models.SlugField(blank=True, null=True, max_length=256)
30class ManualTopicBlock(blocks.StructBlock):
31 heading = blocks.CharBlock(required=False)
32 field_slug = blocks.CharBlock(required=True)
33 paragraph = blocks.RichTextBlock(required=False)
34 image = ImageChooserBlock(required=False)
35 table = TableBlock(required=False, template="pages/blocks/table.html")
37 class Meta:
38 template = "pages/blocks/manual_topic_block.html"
41class IndexPage(Page):
42 intro = models.CharField(max_length=256, blank=True, null=True)
43 text = RichTextField(blank=True)
45 content_panels = Page.content_panels + [
46 FieldPanel("intro", classname="full"),
47 FieldPanel("text", classname="full"),
48 ]
51class IndexPageSearch(Page):
52 intro = models.CharField(max_length=256, blank=True, null=True)
53 text = RichTextField(blank=True)
55 content_panels = Page.content_panels + [
56 FieldPanel("intro", classname="full"),
57 FieldPanel("text", classname="full"),
58 ]
61class ManualIndexPage(Page):
62 intro = models.CharField(max_length=256, blank=True, null=True)
63 text = RichTextField(blank=True)
65 content_panels = Page.content_panels + [
66 FieldPanel("intro", classname="full"),
67 FieldPanel("text", classname="full"),
68 ]
70 def class_name(self):
71 return self.__class__.__name__
73 def save(self, *args, **kwargs):
74 if not kwargs.get("update_fields"):
75 # Generate new table of contents tree
76 generate_toc_tree(slug="help")
78 return super().save(*args, **kwargs)
81class ManualPage(Page):
82 """
83 query in django views using:
84 p = ManualPage.objects.get(id=7)
85 p.body[0].__dict__
87 """
89 intro = models.CharField(max_length=256, blank=True, null=True)
90 body = StreamField([("topic", ManualTopicBlock())], blank=True, null=True)
91 search_index_exclude = models.BooleanField(default=False)
93 content_panels = Page.content_panels + [
94 FieldPanel("intro"),
95 FieldPanel("search_index_exclude"),
96 StreamFieldPanel("body"),
97 ]
99 search_fields = Page.search_fields + [ # Inherit search_fields from Page
100 index.SearchField("intro"),
101 index.SearchField("body"),
102 ]
104 @classmethod
105 def get_indexed_objects(cls):
106 return cls.objects.filter(search_index_exclude=False)
108 def class_name(self):
109 return self.__class__.__name__
111 def save(self, *args, **kwargs):
112 if not kwargs.get("update_fields"):
113 # Generate new table of contents tree
114 generate_toc_tree(slug="help")
116 return super().save(*args, **kwargs)
119class TeamMemberIndexPage(Page):
120 intro = RichTextField(blank=True)
122 content_panels = Page.content_panels + [FieldPanel("intro", classname="full")]
125class LongTextBlock(blocks.StructBlock):
126 heading = blocks.CharBlock(required=False)
127 paragraph = blocks.RichTextBlock(required=False)
128 image = ImageChooserBlock(required=False)
129 slogan = blocks.CharBlock(required=False)
131 class Meta:
132 template = "pages/blocks/long_text_block.html"
135class LandingPage(Page):
136 subtitle = models.CharField(max_length=256, blank=True, null=True)
137 short_description = RichTextField(blank=True)
138 project_description = StreamField(
139 [("project_description", LongTextBlock())], blank=True, null=True
140 )
141 advisory_board = RichTextField(blank=True)
143 content_panels = Page.content_panels + [
144 FieldPanel("subtitle"),
145 FieldPanel("short_description"),
146 InlinePanel("slogans_item", label="Slogan"),
147 StreamFieldPanel("project_description"),
148 FieldPanel("advisory_board"),
149 InlinePanel("team_member", label="Team Member"),
150 InlinePanel("news_item", label="News Item"),
151 ]
154class SlogansItem(Orderable):
155 page = ParentalKey(
156 LandingPage, on_delete=models.CASCADE, related_name="slogans_item"
157 )
158 title = models.CharField(max_length=256, blank=True, null=True)
159 text = RichTextField(blank=True)
160 panels = [
161 FieldPanel("title"),
162 FieldPanel("text"),
163 ]
166class NewsItem(Orderable):
167 page = ParentalKey(LandingPage, on_delete=models.CASCADE, related_name="news_item")
168 title = models.CharField(max_length=256, blank=True, null=True)
169 text = RichTextField(blank=True)
170 date = models.DateField("Post date", blank=True, null=True)
172 panels = [
173 FieldPanel("date"),
174 FieldPanel("title"),
175 FieldPanel("text"),
176 ]
179class TeamMemberEntry(Orderable):
180 page = ParentalKey(
181 LandingPage, on_delete=models.CASCADE, related_name="team_member"
182 )
183 name = models.CharField(max_length=256, blank=True, null=True)
184 role = models.CharField(max_length=256, blank=True, null=True)
185 text = RichTextField(blank=True)
186 link = models.URLField(blank=True)
187 image = models.ForeignKey(
188 "wagtailimages.Image",
189 on_delete=models.PROTECT,
190 related_name="+",
191 blank=True,
192 null=True,
193 )
195 panels = [
196 FieldPanel("name"),
197 FieldPanel("role"),
198 FieldPanel("page"),
199 FieldPanel("text"),
200 FieldPanel("link"),
201 ImageChooserPanel("image"),
202 ]
205class TeamMemberPage(Page):
206 text = RichTextField(blank=True)
207 link = models.URLField(blank=True)
208 image = models.ForeignKey(
209 "wagtailimages.Image",
210 on_delete=models.PROTECT,
211 related_name="+",
212 blank=True,
213 null=True,
214 )
216 search_fields = Page.search_fields + [
217 index.SearchField("text"),
218 ]
220 content_panels = Page.content_panels + [
221 FieldPanel("text", classname="full"),
222 FieldPanel("link"),
223 ImageChooserPanel("image"),
224 ]
227class LicensePage(Page):
228 name = models.CharField(max_length=256, blank=True, null=True)
229 text = RichTextField(blank=True)
230 link = models.URLField(blank=True)
231 image = models.ForeignKey(
232 "wagtailimages.Image",
233 on_delete=models.PROTECT,
234 related_name="+",
235 blank=True,
236 null=True,
237 )
239 search_fields = Page.search_fields + [
240 index.SearchField("name"),
241 index.SearchField("text"),
242 ]
244 content_panels = Page.content_panels + [
245 FieldPanel("name"),
246 FieldPanel("text", classname="full"),
247 FieldPanel("link"),
248 ImageChooserPanel("image"),
249 ]
252class TextPage(Page):
253 text = RichTextField(blank=True)
255 search_fields = Page.search_fields + [
256 index.SearchField("text"),
257 ]
259 content_panels = Page.content_panels + [
260 FieldPanel("text", classname="full"),
261 ]