I'm trying to define 4 GET endpoints (max,min,sum,avg) to access by REST. I did this but making 4 views, and I want to know if I can define the 4 methods in a single view. I can't specify through the url which GET to hit. It's possible?
my urls.py set
urlpatterns =[
path('medidores/', MedidorView.as_view()),
path('mediciones/', MedicionView.as_view()),
path('medicion_max/<str:id>', MedicionMaxView.as_view()),
path('medicion_min/<str:id>', MedicionMinView.as_view()),
path('medicion_total/<str:id>', MedicionTotalView.as_view()),
path('medicion_prom/<str:id>', MedicionPromedioView.as_view())
]
my view.py set
class MedicionMaxView(View):
def get(self, request, id):
return JsonResponse(Medicion.objects.filter(medidor=id).aggregate(Max('consumo_kwh')))
class MedicionMinView(View):
def get(self, request, id):
return JsonResponse(Medicion.objects.filter(medidor=id).aggregate(Min('consumo_kwh')))
class MedicionTotalView(View):
def get(self, request, id):
return JsonResponse(Medicion.objects.filter(medidor=id).aggregate(Sum('consumo_kwh')))
class MedicionPromedioView(View):
def get(self, request, id):
return JsonResponse(Medicion.objects.filter(medidor=id).aggregate(Avg('consumo_kwh')))
Separate by name in urls but not have effect
CodePudding user response:
Yes, you can!
as_view()
accepts parameters, so you can have one view like:
class MedicionView(View):
aggregation=""
def get(self, request, id):
if self.aggregation == 'max':
return JsonResponse(Medicion.objects.filter(medidor=id).aggregate(Max('consumo_kwh')))
elif self.aggregation == 'min':
return JsonResponse(Medicion.objects.filter(medidor=id).aggregate(Min('consumo_kwh')))
elif self.aggregation == 'sum':
return JsonResponse(Medicion.objects.filter(medidor=id).aggregate(Sum('consumo_kwh')))
elif self.aggregation == 'avg':
return JsonResponse(Medicion.objects.filter(medidor=id).aggregate(Avg('consumo_kwh')))
else:
# you can handle it
Side note: you can make this get()
method more clean. For example, move the common calls one level up like Medicion.objects.filter(medidor=id)
Now, can pass the needed aggregation way as parameter to as_view()
with your URLs like:
urlpatterns =[
path('medidores/', MedidorView.as_view()),
path('mediciones/', MedicionView.as_view()),
path('medicion_max/<str:id>', MedicionView.as_view(aggregation='max')),
path('medicion_min/<str:id>', MedicionView.as_view(aggregation='min')),
path('medicion_total/<str:id>', MedicionView.as_view(aggregation='sum')),
path('medicion_prom/<str:id>', MedicionView.as_view(aggregation='avg'))
]
Better way:
You can even make it more clean by having one URL pattern for all of them by having the aggregation type as a URL parameter like:
class MedicionView(View):
def get(self, request, aggregation, id):
if aggregation == 'max':
return JsonResponse(Medicion.objects.filter(medidor=id).aggregate(Max('consumo_kwh')))
elif aggregation == 'min':
return JsonResponse(Medicion.objects.filter(medidor=id).aggregate(Min('consumo_kwh')))
elif aggregation == 'sum':
return JsonResponse(Medicion.objects.filter(medidor=id).aggregate(Sum('consumo_kwh')))
elif aggregation == 'avg':
return JsonResponse(Medicion.objects.filter(medidor=id).aggregate(Avg('consumo_kwh')))
else:
# you can handle it
Now, you can have one URL pattern for them using regular expression:
urlpatterns =[
path('medidores/', MedidorView.as_view()),
path('mediciones/', MedicionView.as_view()),
path(r'medicion/(?P<aggregation>(max|min|sum|avg))/<str:id>', MedicionView.as_view())
]
Update:
If you are following the second solution, don't forget to add the character r
at the beginning of the URL patterns that follow a regex pattern as I did above.