mirror of
https://github.com/TandoorRecipes/recipes.git
synced 2026-01-01 12:18:45 -05:00
remove custom QueryParams with extend_schema decorator
This commit is contained in:
@@ -1,72 +0,0 @@
|
||||
from rest_framework.schemas.openapi import AutoSchema
|
||||
from rest_framework.schemas.utils import is_list_view
|
||||
|
||||
|
||||
class QueryParam(object):
|
||||
def __init__(self, name, description=None, qtype='string', required=False):
|
||||
self.name = name
|
||||
self.description = description
|
||||
self.qtype = qtype
|
||||
self.required = required
|
||||
|
||||
def __str__(self):
|
||||
return f'{self.name}, {self.qtype}, {self.description}'
|
||||
|
||||
|
||||
class QueryParamAutoSchema(AutoSchema):
|
||||
def is_query(self, path, method):
|
||||
return is_list_view(path, method, self.view)
|
||||
|
||||
def get_path_parameters(self, path, method):
|
||||
if not self.is_query(path, method):
|
||||
return super().get_path_parameters(path, method)
|
||||
parameters = super().get_path_parameters(path, method)
|
||||
for q in self.view.query_params:
|
||||
parameters.append({
|
||||
"name": q.name, "in": "query", "required": q.required,
|
||||
"description": q.description,
|
||||
'schema': {'type': q.qtype, },
|
||||
})
|
||||
|
||||
return parameters
|
||||
|
||||
|
||||
class TreeSchema(AutoSchema):
|
||||
def get_path_parameters(self, path, method):
|
||||
if not is_list_view(path, method, self.view):
|
||||
return super(TreeSchema, self).get_path_parameters(path, method)
|
||||
|
||||
api_name = path.split('/')[2]
|
||||
parameters = super().get_path_parameters(path, method)
|
||||
parameters.append({
|
||||
"name": 'query', "in": "query", "required": False,
|
||||
"description": 'Query string matched against {} name.'.format(api_name),
|
||||
'schema': {'type': 'string', },
|
||||
})
|
||||
parameters.append({
|
||||
"name": 'root', "in": "query", "required": False,
|
||||
"description": 'Return first level children of {obj} with ID [int]. Integer 0 will return root {obj}s.'.format(
|
||||
obj=api_name),
|
||||
'schema': {'type': 'integer', },
|
||||
})
|
||||
parameters.append({
|
||||
"name": 'tree', "in": "query", "required": False,
|
||||
"description": 'Return all self and children of {} with ID [int].'.format(api_name),
|
||||
'schema': {'type': 'integer', },
|
||||
})
|
||||
return parameters
|
||||
|
||||
|
||||
class FilterSchema(AutoSchema):
|
||||
def get_path_parameters(self, path, method):
|
||||
if not is_list_view(path, method, self.view):
|
||||
return super(FilterSchema, self).get_path_parameters(path, method)
|
||||
|
||||
api_name = path.split('/')[2]
|
||||
parameters = super().get_path_parameters(path, method)
|
||||
parameters.append({
|
||||
"name": 'query', "in": "query", "required": False,
|
||||
"description": 'Query string matched against {} name.'.format(api_name),
|
||||
'schema': {'type': 'string', },
|
||||
})
|
||||
return parameters
|
||||
@@ -77,7 +77,6 @@ from cookbook.models import (Automation, BookmarkletImport, CookLog, CustomFilte
|
||||
from cookbook.provider.dropbox import Dropbox
|
||||
from cookbook.provider.local import Local
|
||||
from cookbook.provider.nextcloud import Nextcloud
|
||||
from cookbook.schemas import FilterSchema, QueryParam, QueryParamAutoSchema, TreeSchema
|
||||
from cookbook.serializer import (AccessTokenSerializer, AutomationSerializer,
|
||||
AutoMealPlanSerializer, BookmarkletImportListSerializer,
|
||||
BookmarkletImportSerializer, CookLogSerializer,
|
||||
@@ -617,25 +616,26 @@ class FoodViewSet(viewsets.ModelViewSet, TreeMixin):
|
||||
return self.serializer_class
|
||||
|
||||
# TODO I could not find any usage of this and it causes schema generation issues, so commenting it for now
|
||||
# @decorators.action(detail=True, methods=['PUT'], serializer_class=FoodShoppingUpdateSerializer, )
|
||||
# this is used on the Shopping Badge
|
||||
@decorators.action(detail=True, methods=['PUT'], serializer_class=FoodShoppingUpdateSerializer, )
|
||||
# # TODO DRF only allows one action in a decorator action without overriding get_operation_id_base() this should be PUT and DELETE probably
|
||||
# def shopping(self, request, pk):
|
||||
# if self.request.space.demo:
|
||||
# raise PermissionDenied(detail='Not available in demo', code=None)
|
||||
# obj = self.get_object()
|
||||
# shared_users = list(self.request.user.get_shopping_share())
|
||||
# shared_users.append(request.user)
|
||||
# if request.data.get('_delete', False) == 'true':
|
||||
# ShoppingListEntry.objects.filter(food=obj, checked=False, space=request.space, created_by__in=shared_users).delete()
|
||||
# content = {'msg': _(f'{obj.name} was removed from the shopping list.')}
|
||||
# return Response(content, status=status.HTTP_204_NO_CONTENT)
|
||||
#
|
||||
# amount = request.data.get('amount', 1)
|
||||
# unit = request.data.get('unit', None)
|
||||
# content = {'msg': _(f'{obj.name} was added to the shopping list.')}
|
||||
#
|
||||
# ShoppingListEntry.objects.create(food=obj, amount=amount, unit=unit, space=request.space, created_by=request.user)
|
||||
# return Response(content, status=status.HTTP_204_NO_CONTENT)
|
||||
def shopping(self, request, pk):
|
||||
if self.request.space.demo:
|
||||
raise PermissionDenied(detail='Not available in demo', code=None)
|
||||
obj = self.get_object()
|
||||
shared_users = list(self.request.user.get_shopping_share())
|
||||
shared_users.append(request.user)
|
||||
if request.data.get('_delete', False) == 'true':
|
||||
ShoppingListEntry.objects.filter(food=obj, checked=False, space=request.space, created_by__in=shared_users).delete()
|
||||
content = {'msg': _(f'{obj.name} was removed from the shopping list.')}
|
||||
return Response(content, status=status.HTTP_204_NO_CONTENT)
|
||||
|
||||
amount = request.data.get('amount', 1)
|
||||
unit = request.data.get('unit', None)
|
||||
content = {'msg': _(f'{obj.name} was added to the shopping list.')}
|
||||
|
||||
ShoppingListEntry.objects.create(food=obj, amount=amount, unit=unit, space=request.space, created_by=request.user)
|
||||
return Response(content, status=status.HTTP_204_NO_CONTENT)
|
||||
|
||||
@decorators.action(detail=True, methods=['POST'], )
|
||||
def fdc(self, request, pk):
|
||||
@@ -663,13 +663,11 @@ class FoodViewSet(viewsets.ModelViewSet, TreeMixin):
|
||||
json_dumps_params={'indent': 4})
|
||||
|
||||
food.properties_food_amount = 100
|
||||
food.properties_food_unit = Unit.objects.get_or_create(base_unit__iexact='g',
|
||||
space=self.request.space,
|
||||
defaults={
|
||||
'name': 'g',
|
||||
'base_unit': 'g',
|
||||
'space': self.request.space
|
||||
})[0]
|
||||
food.properties_food_unit = Unit.objects.get_or_create(
|
||||
base_unit__iexact='g',
|
||||
space=self.request.space,
|
||||
defaults={ 'name': 'g', 'base_unit': 'g', 'space': self.request.space}
|
||||
)[0]
|
||||
|
||||
food.save()
|
||||
|
||||
@@ -772,9 +770,10 @@ MealPlanViewQueryParameters = [
|
||||
OpenApiParameter(name='meal_type', description=_('Filter meal plans with MealType ID. For multiple repeat parameter.'), type=str),
|
||||
]
|
||||
|
||||
|
||||
@extend_schema_view(
|
||||
list=extend_schema(
|
||||
parameters= MealPlanViewQueryParameters
|
||||
parameters=MealPlanViewQueryParameters
|
||||
),
|
||||
ical=extend_schema(
|
||||
parameters=MealPlanViewQueryParameters,
|
||||
@@ -811,7 +810,7 @@ class MealPlanViewSet(viewsets.ModelViewSet):
|
||||
queryset = queryset.filter(meal_type__in=meal_type)
|
||||
|
||||
return queryset
|
||||
|
||||
|
||||
@action(detail=False)
|
||||
def ical(self, request):
|
||||
from_date = self.request.query_params.get('from_date', None)
|
||||
@@ -819,7 +818,6 @@ class MealPlanViewSet(viewsets.ModelViewSet):
|
||||
return meal_plans_to_ical(self.get_queryset(), f'meal_plan_{from_date}-{to_date}.ics')
|
||||
|
||||
|
||||
|
||||
class AutoPlanViewSet(viewsets.ViewSet):
|
||||
|
||||
def create(self, request):
|
||||
@@ -1136,8 +1134,8 @@ class RecipeViewSet(viewsets.ModelViewSet):
|
||||
serializer_class=RecipeFlatSerializer,
|
||||
)
|
||||
def flat(self, request):
|
||||
qs = Recipe.objects.filter(
|
||||
space=request.space).filter(Q(private=False) | (Q(private=True) & (Q(created_by=self.request.user) | Q(shared=self.request.user)))).all() # TODO limit fields retrieved but .values() kills image
|
||||
# TODO limit fields retrieved but .values() kills image
|
||||
qs = Recipe.objects.filter(space=request.space).filter(Q(private=False) | (Q(private=True) & (Q(created_by=self.request.user) | Q(shared=self.request.user)))).all()
|
||||
|
||||
return Response(self.serializer_class(qs, many=True).data)
|
||||
|
||||
@@ -1284,14 +1282,18 @@ class ViewLogViewSet(viewsets.ModelViewSet):
|
||||
return self.queryset.filter(created_by=self.request.user).filter(space=self.request.space)
|
||||
|
||||
|
||||
@extend_schema_view(
|
||||
list=extend_schema(
|
||||
parameters=[
|
||||
OpenApiParameter(name='recipe', description='Filter for entries with the given recipe', type=int),
|
||||
]
|
||||
)
|
||||
)
|
||||
class CookLogViewSet(viewsets.ModelViewSet):
|
||||
queryset = CookLog.objects
|
||||
serializer_class = CookLogSerializer
|
||||
permission_classes = [CustomIsOwner & CustomTokenHasReadWriteScope]
|
||||
pagination_class = DefaultPagination
|
||||
query_params = [
|
||||
QueryParam(name='recipe', description=_('Filter for entries with the given recipe'), qtype='integer'),
|
||||
]
|
||||
|
||||
def get_queryset(self):
|
||||
if self.request.query_params.get('recipe', None):
|
||||
@@ -1802,6 +1804,7 @@ def get_plan_ical(request, from_date=datetime.date.today(), to_date=None):
|
||||
|
||||
return meal_plans_to_ical(queryset, f'meal_plan_{from_date}-{to_date}.ics')
|
||||
|
||||
|
||||
def meal_plans_to_ical(queryset, filename):
|
||||
cal = Calendar()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user