models.py 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. from datetime import datetime
  2. from django.conf import settings
  3. from django.core.validators import RegexValidator
  4. from django.db import models
  5. from modelcluster.fields import ParentalKey
  6. from wagtail.wagtailadmin.edit_handlers import FieldPanel, InlinePanel
  7. from wagtail.wagtailcore.models import Orderable, Page
  8. from wagtail.wagtailsearch import index
  9. from wagtail.wagtailimages.edit_handlers import ImageChooserPanel
  10. from bakerydemo.base.models import BasePageFieldsMixin
  11. class OperatingHours(models.Model):
  12. """
  13. Django model to capture operating hours for a Location
  14. """
  15. DAY_CHOICES = (
  16. ('MON', 'Monday'),
  17. ('TUES', 'Tuesday'),
  18. ('WED', 'Wednesday'),
  19. ('THUR', 'Thursday'),
  20. ('FRI', 'Friday'),
  21. ('SAT', 'Saturday'),
  22. ('SUN', 'Sunday'),
  23. )
  24. day = models.CharField(
  25. max_length=4,
  26. choices=DAY_CHOICES,
  27. default='MON'
  28. )
  29. opening_time = models.TimeField(
  30. blank=True,
  31. null=True)
  32. closing_time = models.TimeField(
  33. blank=True,
  34. null=True)
  35. closed = models.BooleanField(
  36. "Closed?",
  37. blank=True,
  38. help_text='Tick if location is closed on this day'
  39. )
  40. panels = [
  41. FieldPanel('day'),
  42. FieldPanel('opening_time'),
  43. FieldPanel('closing_time'),
  44. FieldPanel('closed'),
  45. ]
  46. class Meta:
  47. abstract = True
  48. def __str__(self):
  49. if self.opening_time:
  50. opening = self.opening_time.strftime('%H:%M')
  51. else:
  52. opening = '--'
  53. if self.closing_time:
  54. closed = self.opening_time.strftime('%H:%M')
  55. else:
  56. closed = '--'
  57. return '{}: {} - {} {}'.format(
  58. self.day,
  59. opening,
  60. closed,
  61. settings.TIME_ZONE
  62. )
  63. class LocationOperatingHours(Orderable, OperatingHours):
  64. """
  65. Operating Hours entry for a Location
  66. """
  67. location = ParentalKey(
  68. 'LocationPage',
  69. related_name='hours_of_operation'
  70. )
  71. class LocationsIndexPage(BasePageFieldsMixin, Page):
  72. """
  73. Index page for locations
  74. """
  75. subpage_types = ['LocationPage']
  76. def children(self):
  77. return self.get_children().specific().live()
  78. def get_context(self, request):
  79. context = super(LocationsIndexPage, self).get_context(request)
  80. context['locations'] = LocationPage.objects.descendant_of(
  81. self).live().order_by(
  82. 'title')
  83. return context
  84. content_panels = Page.content_panels + [
  85. FieldPanel('introduction', classname="full"),
  86. ImageChooserPanel('image'),
  87. ]
  88. class LocationPage(BasePageFieldsMixin, Page):
  89. """
  90. Detail for a specific bakery location.
  91. """
  92. address = models.TextField()
  93. lat_long = models.CharField(
  94. max_length=36,
  95. help_text="Comma separated lat/long. (Ex. 64.144367, -21.939182) \
  96. Right click Google Maps and select 'What\'s Here'",
  97. validators=[
  98. RegexValidator(
  99. regex='^(\-?\d+(\.\d+)?),\s*(\-?\d+(\.\d+)?)$',
  100. message='Lat Long must be a comma-separated numeric lat and long',
  101. code='invalid_lat_long'
  102. ),
  103. ]
  104. )
  105. # Search index configuration
  106. search_fields = Page.search_fields + [
  107. index.SearchField('address'),
  108. index.SearchField('body'),
  109. ]
  110. # Editor panels configuration
  111. content_panels = BasePageFieldsMixin.content_panels + [
  112. FieldPanel('address', classname="full"),
  113. FieldPanel('lat_long'),
  114. InlinePanel('hours_of_operation', label="Hours of Operation"),
  115. ]
  116. def __str__(self):
  117. return self.title
  118. @property
  119. def operating_hours(self):
  120. hours = self.hours_of_operation.all()
  121. return hours
  122. def is_open(self):
  123. # Determines if the location is currently open
  124. now = datetime.now()
  125. current_time = now.time()
  126. current_day = now.strftime('%a').upper()
  127. try:
  128. self.operating_hours.get(
  129. day=current_day,
  130. opening_time__lte=current_time,
  131. closing_time__gte=current_time
  132. )
  133. return True
  134. except LocationOperatingHours.DoesNotExist:
  135. return False
  136. def get_context(self, request):
  137. context = super(LocationPage, self).get_context(request)
  138. context['lat'] = self.lat_long.split(",")[0]
  139. context['long'] = self.lat_long.split(",")[1]
  140. return context
  141. parent_page_types = ['LocationsIndexPage']