44 EaterySerializerByDay ,
55 EaterySerializerOptimized ,
66)
7+ from django .db .models import Prefetch
78from eatery .util .json import FieldType , error_json , success_json , verify_json_fields
89from django .http import JsonResponse
910from django .shortcuts import get_object_or_404
1516from .permissions import EateryPermission
1617from eatery .datatype .Eatery import EateryID
1718from eatery .models import Eatery
19+ from event .models import Event
1820from .controllers .update_eatery import UpdateEateryController
21+ from memory_profiler import profile
22+ from datetime import timedelta , datetime
23+ from zoneinfo import ZoneInfo
1924
2025
2126class EateryViewSet (viewsets .ModelViewSet ):
@@ -27,29 +32,37 @@ class EateryViewSet(viewsets.ModelViewSet):
2732 serializer_class = EaterySerializer
2833 permission_classes = [EateryPermission ]
2934
35+ @profile
3036 def get_queryset (self ):
3137 """
3238 Override to add prefetch_related for optimization
3339 """
3440 queryset = super ().get_queryset ()
35-
36- # prefetch all related objects to avoid N+1 query problem
37- return queryset .prefetch_related (
38- 'events__menu__items__dietary_preferences' ,
39- 'events__menu__items__allergens'
40- )
4141
42+ # Prefetching only needed for list to prevent N+1
43+ if self .action == "list" :
44+ return queryset .prefetch_related (
45+ "events__menu__items__dietary_preferences" ,
46+ "events__menu__items__allergens" ,
47+ )
48+
49+ return queryset
50+
51+ @profile
52+ @method_decorator (cache_page (60 * 60 * 2 )) # cache for 2 hours
4253 def retrieve (self , request , * args , ** kwargs ):
4354 instance = self .get_object ()
4455 serializer = EaterySerializerOptimized (instance )
4556 return Response (serializer .data )
4657
58+ @profile
4759 @method_decorator (cache_page (60 * 60 * 2 )) # cache for 2 hours
4860 def list (self , request , * args , ** kwargs ):
4961 queryset = self .filter_queryset (self .get_queryset ())
5062 serializer = EaterySerializerOptimized (queryset , many = True )
5163 return Response (serializer .data )
5264
65+ @profile
5366 def get_object (self ):
5467 queryset = self .filter_queryset (self .get_queryset ())
5568 lookup_url_kwarg = self .lookup_url_kwarg or self .lookup_field
@@ -109,10 +122,9 @@ class GetEateriesSimple(APIView):
109122 View all eateries with less information
110123 """
111124
125+ @profile
112126 def get (self , request ):
113- eateries_queryset = Eatery .objects .prefetch_related (
114- 'events'
115- ).all ()
127+ eateries_queryset = Eatery .objects .prefetch_related ("events" ).all ()
116128 eateries = EaterySerializerSimple (eateries_queryset , many = True )
117129 return Response (eateries .data )
118130
@@ -122,16 +134,34 @@ class GetEateriesByDay(APIView):
122134 Get all eatery information by day
123135 """
124136
137+ @profile
125138 @method_decorator (cache_page (60 * 60 * 2 )) # cache for 2 hours
126139 def get (self , request , day ):
140+ now = datetime .now (ZoneInfo ("America/New_York" ))
141+ start_date = now .replace (hour = 0 , minute = 0 , second = 0 , microsecond = 0 ) + timedelta (
142+ days = day
143+ )
144+ end_date = start_date + timedelta (days = 1 )
145+
146+ start_unix = int (start_date .timestamp ())
147+ end_unix = int (end_date .timestamp ())
148+
149+ filtered_events_prefetch = Prefetch (
150+ "events" ,
151+ queryset = Event .objects .filter (
152+ start__gte = start_unix , start__lt = end_unix
153+ ).prefetch_related (
154+ "menu__items__dietary_preferences" , "menu__items__allergens"
155+ ),
156+ to_attr = "filtered_events" ,
157+ )
158+
127159 eateries_queryset = Eatery .objects .prefetch_related (
128- 'events__menu__items__dietary_preferences' ,
129- 'events__menu__items__allergens'
160+ filtered_events_prefetch
130161 ).exclude (events__event_description = "Open" )
131-
162+
132163 eateries = EaterySerializerByDay (
133164 eateries_queryset ,
134165 many = True ,
135- context = {"day" : day },
136166 )
137- return Response (eateries .data )
167+ return Response (eateries .data )
0 commit comments