models.py 4.6 KB

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