Hide keyboard shortcuts

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 

12 

13 

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() 

23 

24 

25class TocTree(models.Model): 

26 html = models.TextField(blank=True, null=True) 

27 slug = models.SlugField(blank=True, null=True, max_length=256) 

28 

29 

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") 

36 

37 class Meta: 

38 template = "pages/blocks/manual_topic_block.html" 

39 

40 

41class IndexPage(Page): 

42 intro = models.CharField(max_length=256, blank=True, null=True) 

43 text = RichTextField(blank=True) 

44 

45 content_panels = Page.content_panels + [ 

46 FieldPanel("intro", classname="full"), 

47 FieldPanel("text", classname="full"), 

48 ] 

49 

50 

51class IndexPageSearch(Page): 

52 intro = models.CharField(max_length=256, blank=True, null=True) 

53 text = RichTextField(blank=True) 

54 

55 content_panels = Page.content_panels + [ 

56 FieldPanel("intro", classname="full"), 

57 FieldPanel("text", classname="full"), 

58 ] 

59 

60 

61class ManualIndexPage(Page): 

62 intro = models.CharField(max_length=256, blank=True, null=True) 

63 text = RichTextField(blank=True) 

64 

65 content_panels = Page.content_panels + [ 

66 FieldPanel("intro", classname="full"), 

67 FieldPanel("text", classname="full"), 

68 ] 

69 

70 def class_name(self): 

71 return self.__class__.__name__ 

72 

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") 

77 

78 return super().save(*args, **kwargs) 

79 

80 

81class ManualPage(Page): 

82 """ 

83 query in django views using: 

84 p = ManualPage.objects.get(id=7) 

85 p.body[0].__dict__ 

86 

87 """ 

88 

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) 

92 

93 content_panels = Page.content_panels + [ 

94 FieldPanel("intro"), 

95 FieldPanel("search_index_exclude"), 

96 StreamFieldPanel("body"), 

97 ] 

98 

99 search_fields = Page.search_fields + [ # Inherit search_fields from Page 

100 index.SearchField("intro"), 

101 index.SearchField("body"), 

102 ] 

103 

104 @classmethod 

105 def get_indexed_objects(cls): 

106 return cls.objects.filter(search_index_exclude=False) 

107 

108 def class_name(self): 

109 return self.__class__.__name__ 

110 

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") 

115 

116 return super().save(*args, **kwargs) 

117 

118 

119class TeamMemberIndexPage(Page): 

120 intro = RichTextField(blank=True) 

121 

122 content_panels = Page.content_panels + [FieldPanel("intro", classname="full")] 

123 

124 

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) 

130 

131 class Meta: 

132 template = "pages/blocks/long_text_block.html" 

133 

134 

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) 

142 

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 ] 

152 

153 

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 ] 

164 

165 

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) 

171 

172 panels = [ 

173 FieldPanel("date"), 

174 FieldPanel("title"), 

175 FieldPanel("text"), 

176 ] 

177 

178 

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 ) 

194 

195 panels = [ 

196 FieldPanel("name"), 

197 FieldPanel("role"), 

198 FieldPanel("page"), 

199 FieldPanel("text"), 

200 FieldPanel("link"), 

201 ImageChooserPanel("image"), 

202 ] 

203 

204 

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 ) 

215 

216 search_fields = Page.search_fields + [ 

217 index.SearchField("text"), 

218 ] 

219 

220 content_panels = Page.content_panels + [ 

221 FieldPanel("text", classname="full"), 

222 FieldPanel("link"), 

223 ImageChooserPanel("image"), 

224 ] 

225 

226 

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 ) 

238 

239 search_fields = Page.search_fields + [ 

240 index.SearchField("name"), 

241 index.SearchField("text"), 

242 ] 

243 

244 content_panels = Page.content_panels + [ 

245 FieldPanel("name"), 

246 FieldPanel("text", classname="full"), 

247 FieldPanel("link"), 

248 ImageChooserPanel("image"), 

249 ] 

250 

251 

252class TextPage(Page): 

253 text = RichTextField(blank=True) 

254 

255 search_fields = Page.search_fields + [ 

256 index.SearchField("text"), 

257 ] 

258 

259 content_panels = Page.content_panels + [ 

260 FieldPanel("text", classname="full"), 

261 ]