-
Notifications
You must be signed in to change notification settings - Fork 566
/
Copy pathmodels.py
371 lines (330 loc) · 11.4 KB
/
models.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
from __future__ import unicode_literals
from django.db import models
from modelcluster.fields import ParentalKey
from modelcluster.models import ClusterableModel
from wagtail.admin.edit_handlers import (
FieldPanel,
FieldRowPanel,
InlinePanel,
MultiFieldPanel,
PageChooserPanel,
StreamFieldPanel,
)
from wagtail.core.fields import RichTextField, StreamField
from wagtail.core.models import Collection, Page
from wagtail.contrib.forms.models import AbstractEmailForm, AbstractFormField
from wagtail.images.edit_handlers import ImageChooserPanel
from wagtail.search import index
from wagtail.snippets.models import register_snippet
from .blocks import BaseStreamBlock
@register_snippet
class People(index.Indexed, ClusterableModel):
"""
A Django model to store People objects.
It uses the `@register_snippet` decorator to allow it to be accessible
via the Snippets UI (e.g. /admin/snippets/base/people/)
`People` uses the `ClusterableModel`, which allows the relationship with
another model to be stored locally to the 'parent' model (e.g. a PageModel)
until the parent is explicitly saved. This allows the editor to use the
'Preview' button, to preview the content, without saving the relationships
to the database.
https://github.com/wagtail/django-modelcluster
"""
first_name = models.CharField("First name", max_length=254)
last_name = models.CharField("Last name", max_length=254)
job_title = models.CharField("Job title", max_length=254)
image = models.ForeignKey(
'wagtailimages.Image',
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name='+'
)
panels = [
MultiFieldPanel([
FieldRowPanel([
FieldPanel('first_name', classname="col6"),
FieldPanel('last_name', classname="col6"),
])
], "Name"),
FieldPanel('job_title'),
ImageChooserPanel('image')
]
search_fields = [
index.SearchField('first_name'),
index.SearchField('last_name'),
]
@property
def thumb_image(self):
# Returns an empty string if there is no profile pic or the rendition
# file can't be found.
try:
return self.image.get_rendition('fill-50x50').img_tag()
except: # noqa: E722 FIXME: remove bare 'except:'
return ''
def __str__(self):
return '{} {}'.format(self.first_name, self.last_name)
class Meta:
verbose_name = 'Person'
verbose_name_plural = 'People'
@register_snippet
class FooterText(models.Model):
"""
This provides editable text for the site footer. Again it uses the decorator
`register_snippet` to allow it to be accessible via the admin. It is made
accessible on the template via a template tag defined in base/templatetags/
navigation_tags.py
"""
body = RichTextField()
panels = [
FieldPanel('body'),
]
def __str__(self):
return "Footer text"
class Meta:
verbose_name_plural = 'Footer Text'
class StandardPage(Page):
"""
A generic content page. On this demo site we use it for an about page but
it could be used for any type of page content that only needs a title,
image, introduction and body field
"""
introduction = models.TextField(
help_text='Text to describe the page',
blank=True)
image = models.ForeignKey(
'wagtailimages.Image',
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name='+',
help_text='Landscape mode only; horizontal width between 1000px and 3000px.'
)
body = StreamField(
BaseStreamBlock(), verbose_name="Page body", blank=True
)
content_panels = Page.content_panels + [
FieldPanel('introduction', classname="full"),
StreamFieldPanel('body'),
ImageChooserPanel('image'),
]
class HomePage(Page):
"""
The Home Page. This looks slightly more complicated than it is. You can
see if you visit your site and edit the homepage that it is split between
a:
- Hero area
- Body area
- A promotional area
- Moveable featured site sections
"""
# Hero section of HomePage
image = models.ForeignKey(
'wagtailimages.Image',
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name='+',
help_text='Homepage image'
)
hero_text = models.CharField(
max_length=255,
help_text='Write an introduction for the bakery'
)
hero_cta = models.CharField(
verbose_name='Hero CTA',
max_length=255,
help_text='Text to display on Call to Action'
)
hero_cta_link = models.ForeignKey(
'wagtailcore.Page',
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name='+',
verbose_name='Hero CTA link',
help_text='Choose a page to link to for the Call to Action'
)
# Body section of the HomePage
body = StreamField(
BaseStreamBlock(), verbose_name="Home content block", blank=True
)
# Promo section of the HomePage
promo_image = models.ForeignKey(
'wagtailimages.Image',
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name='+',
help_text='Promo image'
)
promo_title = models.CharField(
null=True,
blank=True,
max_length=255,
help_text='Title to display above the promo copy'
)
promo_text = RichTextField(
null=True,
blank=True,
help_text='Write some promotional copy'
)
# Featured sections on the HomePage
# You will see on templates/base/home_page.html that these are treated
# in different ways, and displayed in different areas of the page.
# Each list their children items that we access via the children function
# that we define on the individual Page models e.g. BlogIndexPage
featured_section_1_title = models.CharField(
null=True,
blank=True,
max_length=255,
help_text='Title to display above the promo copy'
)
featured_section_1 = models.ForeignKey(
'wagtailcore.Page',
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name='+',
help_text='First featured section for the homepage. Will display up to '
'three child items.',
verbose_name='Featured section 1'
)
featured_section_2_title = models.CharField(
null=True,
blank=True,
max_length=255,
help_text='Title to display above the promo copy'
)
featured_section_2 = models.ForeignKey(
'wagtailcore.Page',
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name='+',
help_text='Second featured section for the homepage. Will display up to '
'three child items.',
verbose_name='Featured section 2'
)
featured_section_3_title = models.CharField(
null=True,
blank=True,
max_length=255,
help_text='Title to display above the promo copy'
)
featured_section_3 = models.ForeignKey(
'wagtailcore.Page',
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name='+',
help_text='Third featured section for the homepage. Will display up to '
'six child items.',
verbose_name='Featured section 3'
)
content_panels = Page.content_panels + [
MultiFieldPanel([
ImageChooserPanel('image'),
FieldPanel('hero_text', classname="full"),
MultiFieldPanel([
FieldPanel('hero_cta'),
PageChooserPanel('hero_cta_link'),
]),
], heading="Hero section"),
MultiFieldPanel([
ImageChooserPanel('promo_image'),
FieldPanel('promo_title'),
FieldPanel('promo_text'),
], heading="Promo section"),
StreamFieldPanel('body'),
MultiFieldPanel([
MultiFieldPanel([
FieldPanel('featured_section_1_title'),
PageChooserPanel('featured_section_1'),
]),
MultiFieldPanel([
FieldPanel('featured_section_2_title'),
PageChooserPanel('featured_section_2'),
]),
MultiFieldPanel([
FieldPanel('featured_section_3_title'),
PageChooserPanel('featured_section_3'),
]),
], heading="Featured homepage sections", classname="collapsible")
]
def __str__(self):
return self.title
class GalleryPage(Page):
"""
This is a page to list locations from the selected Collection. We use a Q
object to list any Collection created (/admin/collections/) even if they
contain no items. In this demo we use it for a GalleryPage,
and is intended to show the extensibility of this aspect of Wagtail
"""
introduction = models.TextField(
help_text='Text to describe the page',
blank=True)
image = models.ForeignKey(
'wagtailimages.Image',
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name='+',
help_text='Landscape mode only; horizontal width between 1000px and '
'3000px.'
)
body = StreamField(
BaseStreamBlock(), verbose_name="Page body", blank=True
)
collection = models.ForeignKey(
Collection,
limit_choices_to=~models.Q(name__in=['Root']),
null=True,
blank=True,
on_delete=models.SET_NULL,
help_text='Select the image collection for this gallery.'
)
content_panels = Page.content_panels + [
FieldPanel('introduction', classname="full"),
StreamFieldPanel('body'),
ImageChooserPanel('image'),
FieldPanel('collection'),
]
# Defining what content type can sit under the parent. Since it's a blank
# array no subpage can be added
subpage_types = []
class FormField(AbstractFormField):
"""
Wagtailforms is a module to introduce simple forms on a Wagtail site. It
isn't intended as a replacement to Django's form support but as a quick way
to generate a general purpose data-collection form or contact form
without having to write code. We use it on the site for a contact form. You
can read more about Wagtail forms at:
http://docs.wagtail.io/en/latest/reference/contrib/forms/index.html
"""
page = ParentalKey('FormPage', related_name='form_fields', on_delete=models.CASCADE)
class FormPage(AbstractEmailForm):
image = models.ForeignKey(
'wagtailimages.Image',
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name='+'
)
body = StreamField(BaseStreamBlock())
thank_you_text = RichTextField(blank=True)
# Note how we include the FormField object via an InlinePanel using the
# related_name value
content_panels = AbstractEmailForm.content_panels + [
ImageChooserPanel('image'),
StreamFieldPanel('body'),
InlinePanel('form_fields', label="Form fields"),
FieldPanel('thank_you_text', classname="full"),
MultiFieldPanel([
FieldRowPanel([
FieldPanel('from_address', classname="col6"),
FieldPanel('to_address', classname="col6"),
]),
FieldPanel('subject'),
], "Email"),
]