-
Notifications
You must be signed in to change notification settings - Fork 688
Expand file tree
/
Copy pathmodels.py
More file actions
209 lines (182 loc) · 6.45 KB
/
models.py
File metadata and controls
209 lines (182 loc) · 6.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
from datetime import datetime
from django.conf import settings
from django.core.validators import RegexValidator
from django.db import models
from modelcluster.fields import ParentalKey
from wagtail.core.fields import StreamField
from wagtail.admin.edit_handlers import FieldPanel, InlinePanel, StreamFieldPanel
from wagtail.core.models import Orderable, Page
from wagtail.search import index
from wagtail.images.edit_handlers import ImageChooserPanel
from bakerydemo.base.blocks import BaseStreamBlock
from bakerydemo.locations.choices import DAY_CHOICES
class OperatingHours(models.Model):
"""
A Django model to capture operating hours for a Location
"""
day = models.CharField(
max_length=4,
choices=DAY_CHOICES,
default='MON'
)
opening_time = models.TimeField(
blank=True,
null=True
)
closing_time = models.TimeField(
blank=True,
null=True
)
closed = models.BooleanField(
"Closed?",
blank=True,
help_text='Tick if location is closed on this day'
)
panels = [
FieldPanel('day'),
FieldPanel('opening_time'),
FieldPanel('closing_time'),
FieldPanel('closed'),
]
class Meta:
abstract = True
def __str__(self):
if self.opening_time:
opening = self.opening_time.strftime('%H:%M')
else:
opening = '--'
if self.closing_time:
closed = self.closing_time.strftime('%H:%M')
else:
closed = '--'
return '{}: {} - {} {}'.format(
self.day,
opening,
closed,
settings.TIME_ZONE
)
class LocationOperatingHours(Orderable, OperatingHours):
"""
A model creating a relationship between the OperatingHours and Location
Note that unlike BlogPeopleRelationship we don't include a ForeignKey to
OperatingHours as we don't need that relationship (e.g. any Location open
a certain day of the week). The ParentalKey is the minimum required to
relate the two objects to one another. We use the ParentalKey's related_
name to access it from the LocationPage admin
"""
location = ParentalKey(
'LocationPage',
related_name='hours_of_operation',
on_delete=models.CASCADE
)
class LocationsIndexPage(Page):
"""
A Page model that creates an index page (a listview)
"""
introduction = models.TextField(
help_text='Text to describe the page',
blank=True)
image = models.ForeignKey(
'wagtailimages.Image',
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name='+',
help_text='Landscape mode only; horizontal width between 1000px and 3000px.'
)
# Only LocationPage objects can be added underneath this index page
subpage_types = ['LocationPage']
# Allows children of this indexpage to be accessible via the indexpage
# object on templates. We use this on the homepage to show featured
# sections of the site and their child pages
def children(self):
return self.get_children().specific().live()
# Overrides the context to list all child
# items, that are live, by the date that they were published
# http://docs.wagtail.io/en/latest/getting_started/tutorial.html#overriding-context
def get_context(self, request):
context = super(LocationsIndexPage, self).get_context(request)
context['locations'] = LocationPage.objects.descendant_of(
self).live().order_by(
'title')
return context
content_panels = Page.content_panels + [
FieldPanel('introduction', classname="full"),
ImageChooserPanel('image'),
]
class LocationPage(Page):
"""
Detail for a specific bakery location.
"""
introduction = models.TextField(
help_text='Text to describe the page',
blank=True)
image = models.ForeignKey(
'wagtailimages.Image',
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name='+',
help_text='Landscape mode only; horizontal width between 1000px and 3000px.'
)
body = StreamField(
BaseStreamBlock(), verbose_name="Page body", blank=True
)
address = models.TextField()
lat_long = models.CharField(
max_length=36,
help_text="Comma separated lat/long. (Ex. 64.144367, -21.939182) \
Right click Google Maps and select 'What\'s Here'",
validators=[
RegexValidator(
regex=r'^(\-?\d+(\.\d+)?),\s*(\-?\d+(\.\d+)?)$',
message='Lat Long must be a comma-separated numeric lat and long',
code='invalid_lat_long'
),
]
)
# Search index configuration
search_fields = Page.search_fields + [
index.SearchField('address'),
index.SearchField('body'),
]
# Fields to show to the editor in the admin view
content_panels = [
FieldPanel('title', classname="full"),
FieldPanel('introduction', classname="full"),
ImageChooserPanel('image'),
StreamFieldPanel('body'),
FieldPanel('address', classname="full"),
FieldPanel('lat_long'),
InlinePanel('hours_of_operation', label="Hours of Operation"),
]
def __str__(self):
return self.title
@property
def operating_hours(self):
hours = self.hours_of_operation.all()
return hours
# Determines if the location is currently open. It is timezone naive
def is_open(self):
now = datetime.now()
current_time = now.time()
current_day = now.strftime('%a').upper()
try:
self.operating_hours.get(
day=current_day,
opening_time__lte=current_time,
closing_time__gte=current_time
)
return True
except LocationOperatingHours.DoesNotExist:
return False
# Makes additional context available to the template so that we can access
# the latitude, longitude and map API key to render the map
def get_context(self, request):
context = super(LocationPage, self).get_context(request)
context['lat'] = self.lat_long.split(",")[0]
context['long'] = self.lat_long.split(",")[1]
context['google_map_api_key'] = settings.GOOGLE_MAP_API_KEY
return context
# Can only be placed under a LocationsIndexPage object
parent_page_types = ['LocationsIndexPage']