models.py 3.9 KB

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