models.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. from django import forms
  2. from django.db import models
  3. from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
  4. from modelcluster.fields import ParentalManyToManyField
  5. from wagtail.wagtailadmin.edit_handlers import FieldPanel, MultiFieldPanel
  6. from wagtail.wagtailcore.models import Page
  7. from wagtail.wagtailsearch import index
  8. from wagtail.wagtailsnippets.models import register_snippet
  9. from wagtail.wagtailimages.edit_handlers import ImageChooserPanel
  10. from bakerydemo.base.models import BasePageFieldsMixin
  11. @register_snippet
  12. class Country(models.Model):
  13. """
  14. Standard Django model to store set of countries of origin.
  15. Exposed in the Wagtail admin via Snippets.
  16. """
  17. title = models.CharField(max_length=100)
  18. def __str__(self):
  19. return self.title
  20. class Meta:
  21. verbose_name_plural = "Countries of Origin"
  22. @register_snippet
  23. class BreadIngredient(models.Model):
  24. """
  25. Standard Django model used as a Snippet in the BreadPage model.
  26. Demonstrates ManyToMany relationship.
  27. """
  28. name = models.CharField(max_length=255)
  29. panels = [
  30. FieldPanel('name'),
  31. ]
  32. def __str__(self):
  33. return self.name
  34. class Meta:
  35. verbose_name_plural = 'Bread ingredients'
  36. @register_snippet
  37. class BreadType(models.Model):
  38. """
  39. Standard Django model used as a Snippet in the BreadPage model.
  40. """
  41. title = models.CharField(max_length=255)
  42. panels = [
  43. FieldPanel('title'),
  44. ]
  45. def __str__(self):
  46. return self.title
  47. class Meta:
  48. verbose_name_plural = "Bread types"
  49. class BreadPage(BasePageFieldsMixin, Page):
  50. """
  51. Detail view for a specific bread
  52. """
  53. origin = models.ForeignKey(
  54. Country,
  55. on_delete=models.SET_NULL,
  56. null=True,
  57. blank=True,
  58. )
  59. bread_type = models.ForeignKey(
  60. 'breads.BreadType',
  61. null=True,
  62. blank=True,
  63. on_delete=models.SET_NULL,
  64. related_name='+'
  65. )
  66. ingredients = ParentalManyToManyField('BreadIngredient', blank=True)
  67. content_panels = BasePageFieldsMixin.content_panels + [
  68. FieldPanel('origin'),
  69. FieldPanel('bread_type'),
  70. MultiFieldPanel(
  71. [
  72. FieldPanel(
  73. 'ingredients',
  74. widget=forms.CheckboxSelectMultiple,
  75. ),
  76. ],
  77. heading="Additional Metadata",
  78. classname="collapsible collapsed"
  79. ),
  80. ]
  81. search_fields = Page.search_fields + [
  82. index.SearchField('title'),
  83. index.SearchField('body'),
  84. ]
  85. parent_page_types = ['BreadsIndexPage']
  86. class BreadsIndexPage(BasePageFieldsMixin, Page):
  87. """
  88. Index page for breads. We don't have any fields within our model but we need
  89. to alter the page model's context to return the child page objects - the
  90. BreadPage - so that it works as an index page.
  91. """
  92. subpage_types = ['BreadPage']
  93. def get_breads(self):
  94. return BreadPage.objects.live().descendant_of(
  95. self).order_by('-first_published_at')
  96. def children(self):
  97. return self.get_children().specific().live()
  98. def paginate(self, request, *args):
  99. page = request.GET.get('page')
  100. paginator = Paginator(self.get_breads(), 12)
  101. try:
  102. pages = paginator.page(page)
  103. except PageNotAnInteger:
  104. pages = paginator.page(1)
  105. except EmptyPage:
  106. pages = paginator.page(paginator.num_pages)
  107. return pages
  108. def get_context(self, request):
  109. context = super(BreadsIndexPage, self).get_context(request)
  110. breads = self.paginate(request, self.get_breads())
  111. context['breads'] = breads
  112. return context
  113. content_panels = Page.content_panels + [
  114. FieldPanel('introduction', classname="full"),
  115. ImageChooserPanel('image'),
  116. ]