models.py 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. from __future__ import unicode_literals
  2. from django.db import models
  3. from modelcluster.fields import ParentalKey
  4. from modelcluster.models import ClusterableModel
  5. from wagtail.wagtailcore.models import Page, Orderable, Collection
  6. from wagtail.wagtailsearch import index
  7. from wagtail.wagtailimages.edit_handlers import ImageChooserPanel
  8. from wagtail.wagtailcore.fields import StreamField, RichTextField
  9. from wagtail.wagtailadmin.edit_handlers import (
  10. FieldPanel,
  11. InlinePanel,
  12. FieldRowPanel,
  13. StreamFieldPanel,
  14. MultiFieldPanel,
  15. PageChooserPanel
  16. )
  17. from wagtail.wagtailsnippets.models import register_snippet
  18. from .blocks import BaseStreamBlock
  19. from wagtail.wagtailforms.models import AbstractEmailForm, AbstractFormField
  20. from wagtail.contrib.modeladmin.options import (
  21. ModelAdmin, ModelAdminGroup, modeladmin_register)
  22. @register_snippet
  23. class People(ClusterableModel):
  24. first_name = models.CharField("First name", max_length=254)
  25. last_name = models.CharField("Last name", max_length=254)
  26. job_title = models.CharField("Job title", max_length=254)
  27. image = models.ForeignKey(
  28. 'wagtailimages.Image',
  29. null=True,
  30. blank=True,
  31. on_delete=models.SET_NULL,
  32. related_name='+'
  33. )
  34. panels = [
  35. FieldPanel('first_name', classname="col6"),
  36. FieldPanel('last_name', classname="col6"),
  37. FieldPanel('job_title'),
  38. ImageChooserPanel('image')
  39. ]
  40. search_fields = Page.search_fields + [
  41. index.SearchField('first_name'),
  42. index.SearchField('last_name'),
  43. ]
  44. @property
  45. def thumb_image(self):
  46. # fail silently if there is no profile pic or the rendition file can't
  47. # be found. Note @richbrennan worked out how to do this...
  48. try:
  49. return self.image.get_rendition('fill-50x50').img_tag()
  50. except:
  51. return ''
  52. def __str__(self):
  53. return self.first_name + " " + self.last_name
  54. class Meta:
  55. verbose_name = 'Person'
  56. verbose_name_plural = 'People'
  57. @register_snippet
  58. class FooterText(models.Model):
  59. body = RichTextField()
  60. panels = [
  61. FieldPanel('body'),
  62. ]
  63. def __str__(self):
  64. return "Footer text"
  65. class Meta:
  66. verbose_name_plural = 'Footer Text'
  67. class AboutLocationRelationship(Orderable, models.Model):
  68. """
  69. This defines the relationship between the `LocationPage` within the `locations`
  70. app and the About page below allowing us to add locations to the about
  71. section.
  72. """
  73. page = ParentalKey(
  74. 'AboutPage', related_name='location_about_relationship'
  75. )
  76. locations = models.ForeignKey(
  77. 'locations.LocationPage', related_name='about_location_relationship'
  78. )
  79. panels = [
  80. PageChooserPanel('locations')
  81. ]
  82. class AboutPage(Page):
  83. """
  84. The About Page
  85. """
  86. image = models.ForeignKey(
  87. 'wagtailimages.Image',
  88. null=True,
  89. blank=True,
  90. on_delete=models.SET_NULL,
  91. related_name='+',
  92. help_text='Location image'
  93. )
  94. body = StreamField(
  95. BaseStreamBlock(), verbose_name="About page detail", blank=True
  96. )
  97. # We've defined the StreamBlock() within blocks.py that we've imported on
  98. # line 12. Defining it in a different file gives us consistency across the
  99. # site, though StreamFields _can_ be created on a per model basis if you
  100. # have a use case for it
  101. content_panels = Page.content_panels + [
  102. ImageChooserPanel('image'),
  103. StreamFieldPanel('body'),
  104. InlinePanel(
  105. 'location_about_relationship',
  106. label='Locations',
  107. min_num=None
  108. ),
  109. ]
  110. # parent_page_types = [
  111. # 'home.HomePage'
  112. # ]
  113. # Defining what content type can sit under the parent
  114. # The empty array means that no children can be placed under the
  115. # LocationPage page model
  116. subpage_types = []
  117. # api_fields = ['image', 'body']
  118. def getImageCollections():
  119. # We return all collections to a list that don't have the name root.
  120. try:
  121. collection_images = [(
  122. collection.id, collection.name
  123. ) for collection in Collection.objects.all().exclude(
  124. name='Root'
  125. )]
  126. return collection_images
  127. except:
  128. return [('', '')]
  129. def __str__(self):
  130. return self.title
  131. class HomePage(Page):
  132. """
  133. The Home Page
  134. """
  135. image = models.ForeignKey(
  136. 'wagtailimages.Image',
  137. null=True,
  138. blank=True,
  139. on_delete=models.SET_NULL,
  140. related_name='+',
  141. help_text='Location image'
  142. )
  143. body = StreamField(
  144. BaseStreamBlock(), verbose_name="Home page detail", blank=True
  145. )
  146. content_panels = Page.content_panels + [
  147. ImageChooserPanel('image'),
  148. StreamFieldPanel('body'),
  149. ]
  150. def __str__(self):
  151. return self.title
  152. class GalleryPage(Page):
  153. """
  154. This is a page to list all the locations on the site
  155. """
  156. choices = models.ForeignKey(
  157. Collection,
  158. limit_choices_to=~models.Q(name__in=['Root']),
  159. null=True,
  160. blank=True,
  161. on_delete=models.SET_NULL,
  162. )
  163. image = models.ForeignKey(
  164. 'wagtailimages.Image',
  165. null=True,
  166. blank=True,
  167. on_delete=models.SET_NULL,
  168. related_name='+',
  169. help_text='Location listing image'
  170. )
  171. introduction = models.TextField(
  172. help_text='Text to describe the index page',
  173. blank=True)
  174. content_panels = Page.content_panels + [
  175. FieldPanel('choices'),
  176. ImageChooserPanel('image'),
  177. FieldPanel('introduction')
  178. ]
  179. # parent_page_types = [
  180. # 'home.HomePage'
  181. # ]
  182. # Defining what content type can sit under the parent. Since it's a blank
  183. # array no subpage can be added
  184. subpage_types = [
  185. ]
  186. # api_fields = ['introduction']
  187. class FormField(AbstractFormField):
  188. page = ParentalKey('FormPage', related_name='form_fields')
  189. class FormPage(AbstractEmailForm):
  190. header_image = models.ForeignKey(
  191. 'wagtailimages.Image',
  192. null=True,
  193. blank=True,
  194. on_delete=models.SET_NULL,
  195. related_name='+'
  196. )
  197. body = StreamField(BaseStreamBlock())
  198. thank_you_text = RichTextField(blank=True)
  199. content_panels = AbstractEmailForm.content_panels + [
  200. ImageChooserPanel('header_image'),
  201. StreamFieldPanel('body'),
  202. InlinePanel('form_fields', label="Form fields"),
  203. FieldPanel('thank_you_text', classname="full"),
  204. MultiFieldPanel([
  205. FieldRowPanel([
  206. FieldPanel('from_address', classname="col6"),
  207. FieldPanel('to_address', classname="col6"),
  208. ]),
  209. FieldPanel('subject'),
  210. ], "Email"),
  211. ]
  212. class PeopleModelAdmin(ModelAdmin):
  213. model = People
  214. menu_label = 'People' # ditch this to use verbose_name_plural from model
  215. menu_icon = 'fa-people' # change as required
  216. list_display = ('first_name', 'last_name', 'job_title', 'thumb_image')
  217. class MyModelAdminGroup(ModelAdminGroup):
  218. menu_label = 'WagtailBakery'
  219. menu_icon = 'folder-open-inverse' # change as required
  220. menu_order = 200 # will put in 3rd place (000 being 1st, 100 2nd)
  221. items = (PeopleModelAdmin,)
  222. # When using a ModelAdminGroup class to group several ModelAdmin classes together,
  223. # you only need to register the ModelAdminGroup class with Wagtail:
  224. modeladmin_register(MyModelAdminGroup)