added api pagination for recipes
This commit is contained in:
parent
04488741c4
commit
e676b4bac3
@ -50,7 +50,7 @@ def search_recipes(queryset, params):
|
||||
if search_internal == 'true':
|
||||
queryset = queryset.filter(internal=True)
|
||||
|
||||
if search_limit:
|
||||
queryset = queryset[:int(search_limit)]
|
||||
# if search_limit:
|
||||
# queryset = queryset[:int(search_limit)]
|
||||
|
||||
return queryset
|
||||
|
File diff suppressed because one or more lines are too long
@ -4,6 +4,7 @@ import re
|
||||
import uuid
|
||||
|
||||
import requests
|
||||
import yaml
|
||||
from PIL import Image
|
||||
from annoying.decorators import ajax_request
|
||||
from annoying.functions import get_object_or_None
|
||||
@ -19,8 +20,10 @@ from django.utils.translation import gettext as _
|
||||
from icalendar import Calendar, Event
|
||||
from rest_framework import decorators, viewsets, status
|
||||
from rest_framework.exceptions import APIException, PermissionDenied, NotFound, MethodNotAllowed
|
||||
from rest_framework.pagination import LimitOffsetPagination, PageNumberPagination
|
||||
from rest_framework.parsers import MultiPartParser
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.schemas import AutoSchema
|
||||
from rest_framework.viewsets import ViewSetMixin
|
||||
|
||||
from cookbook.helper.ingredient_parser import parse
|
||||
@ -49,7 +52,8 @@ from cookbook.serializer import (FoodSerializer, IngredientSerializer,
|
||||
StorageSerializer, SyncLogSerializer,
|
||||
SyncSerializer, UnitSerializer,
|
||||
UserNameSerializer, UserPreferenceSerializer,
|
||||
ViewLogSerializer, CookLogSerializer, RecipeBookEntrySerializer, RecipeOverviewSerializer, SupermarketSerializer, ImportLogSerializer)
|
||||
ViewLogSerializer, CookLogSerializer, RecipeBookEntrySerializer,
|
||||
RecipeOverviewSerializer, SupermarketSerializer, ImportLogSerializer)
|
||||
from recipes.settings import DEMO
|
||||
from recipe_scrapers import scrape_me, WebsiteNotImplementedError, NoSchemaFoundInWildMode
|
||||
|
||||
@ -248,7 +252,8 @@ class MealTypeViewSet(viewsets.ModelViewSet):
|
||||
permission_classes = [CustomIsOwner]
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = self.queryset.order_by('order', 'id').filter(created_by=self.request.user).filter(space=self.request.space).all()
|
||||
queryset = self.queryset.order_by('order', 'id').filter(created_by=self.request.user).filter(
|
||||
space=self.request.space).all()
|
||||
return queryset
|
||||
|
||||
|
||||
@ -270,29 +275,59 @@ class StepViewSet(viewsets.ModelViewSet):
|
||||
return self.queryset.filter(recipe__space=self.request.space)
|
||||
|
||||
|
||||
class RecipePagination(PageNumberPagination):
|
||||
page_size = 25
|
||||
page_size_query_param = 'page_size'
|
||||
max_page_size = 100
|
||||
|
||||
|
||||
from rest_framework.schemas.openapi import AutoSchema, SchemaGenerator
|
||||
|
||||
|
||||
class RecipeSchema(AutoSchema):
|
||||
|
||||
def get_path_parameters(self, path, method):
|
||||
parameters = super().get_path_parameters(path, method)
|
||||
parameters.append(
|
||||
{
|
||||
"name": 'query',
|
||||
"in": "path",
|
||||
"required": True,
|
||||
"description": 'description',
|
||||
'schema': {
|
||||
'type': 'string', # TODO: integer, pattern, ...
|
||||
},
|
||||
}
|
||||
)
|
||||
return parameters
|
||||
|
||||
|
||||
class RecipeViewSet(viewsets.ModelViewSet):
|
||||
"""
|
||||
list:
|
||||
optional parameters
|
||||
|
||||
- **query**: search recipes for a string contained
|
||||
in the recipe name (case in-sensitive)
|
||||
- **limit**: limits the amount of returned results
|
||||
"""
|
||||
list:
|
||||
optional parameters
|
||||
- **query**: search recipes for a string contained in the recipe name (case in-sensitive)
|
||||
- **limit**: limits the amount of returned results
|
||||
"""
|
||||
queryset = Recipe.objects
|
||||
serializer_class = RecipeSerializer
|
||||
# TODO split read and write permission for meal plan guest
|
||||
permission_classes = [CustomIsShare | CustomIsGuest]
|
||||
|
||||
pagination_class = RecipePagination
|
||||
|
||||
# schema = RecipeSchema
|
||||
|
||||
def get_queryset(self):
|
||||
share = self.request.query_params.get('share', None)
|
||||
if not (share and self.detail):
|
||||
self.queryset = self.queryset.filter(space=self.request.space)
|
||||
|
||||
return search_recipes(self.queryset, self.request.GET)
|
||||
self.queryset = search_recipes(self.queryset, self.request.GET)
|
||||
|
||||
return super().get_queryset()
|
||||
|
||||
# TODO write extensive tests for permissions
|
||||
|
||||
def get_serializer_class(self):
|
||||
if self.action == 'list':
|
||||
return RecipeOverviewSerializer
|
||||
@ -341,7 +376,9 @@ class ShoppingListRecipeViewSet(viewsets.ModelViewSet):
|
||||
permission_classes = [CustomIsOwner | CustomIsShared]
|
||||
|
||||
def get_queryset(self):
|
||||
return self.queryset.filter(Q(shoppinglist__created_by=self.request.user) | Q(shoppinglist__shared=self.request.user)).filter(shoppinglist__space=self.request.space).all()
|
||||
return self.queryset.filter(
|
||||
Q(shoppinglist__created_by=self.request.user) | Q(shoppinglist__shared=self.request.user)).filter(
|
||||
shoppinglist__space=self.request.space).all()
|
||||
|
||||
|
||||
class ShoppingListEntryViewSet(viewsets.ModelViewSet):
|
||||
@ -350,7 +387,9 @@ class ShoppingListEntryViewSet(viewsets.ModelViewSet):
|
||||
permission_classes = [CustomIsOwner | CustomIsShared]
|
||||
|
||||
def get_queryset(self):
|
||||
return self.queryset.filter(Q(shoppinglist__created_by=self.request.user) | Q(shoppinglist__shared=self.request.user)).filter(shoppinglist__space=self.request.space).all()
|
||||
return self.queryset.filter(
|
||||
Q(shoppinglist__created_by=self.request.user) | Q(shoppinglist__shared=self.request.user)).filter(
|
||||
shoppinglist__space=self.request.space).all()
|
||||
|
||||
|
||||
class ShoppingListViewSet(viewsets.ModelViewSet):
|
||||
@ -359,7 +398,8 @@ class ShoppingListViewSet(viewsets.ModelViewSet):
|
||||
permission_classes = [CustomIsOwner | CustomIsShared]
|
||||
|
||||
def get_queryset(self):
|
||||
return self.queryset.filter(Q(created_by=self.request.user) | Q(shared=self.request.user)).filter(space=self.request.space).distinct()
|
||||
return self.queryset.filter(Q(created_by=self.request.user) | Q(shared=self.request.user)).filter(
|
||||
space=self.request.space).distinct()
|
||||
|
||||
def get_serializer_class(self):
|
||||
try:
|
||||
@ -562,7 +602,8 @@ def recipe_from_url_old(request):
|
||||
url = request.POST['url']
|
||||
|
||||
headers = {
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36' # noqa: E501
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36'
|
||||
# noqa: E501
|
||||
}
|
||||
try:
|
||||
response = requests.get(url, headers=headers)
|
||||
|
@ -51,7 +51,6 @@
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
|
||||
@ -60,11 +59,12 @@
|
||||
|
||||
<generic-multiselect @change="genericSelectChanged" parent_variable="search_keywords"
|
||||
:initial_selection="search_keywords"
|
||||
search_function="listKeywords" label="label" style="flex-grow: 1; flex-shrink: 1; flex-basis: 0"
|
||||
search_function="listKeywords" label="label"
|
||||
style="flex-grow: 1; flex-shrink: 1; flex-basis: 0"
|
||||
v-bind:placeholder="$t('Keywords')"></generic-multiselect>
|
||||
|
||||
<b-input-group-append >
|
||||
<b-input-group-text >
|
||||
<b-input-group-append>
|
||||
<b-input-group-text>
|
||||
|
||||
<b-form-checkbox v-model="search_keywords_or" name="check-button" @change="refreshData"
|
||||
class="shadow-none" switch>
|
||||
@ -83,10 +83,11 @@
|
||||
<b-input-group style="margin-top: 1vh">
|
||||
<generic-multiselect @change="genericSelectChanged" parent_variable="search_foods"
|
||||
:initial_selection="search_foods"
|
||||
search_function="listFoods" label="name" style="flex-grow: 1; flex-shrink: 1; flex-basis: 0"
|
||||
search_function="listFoods" label="name"
|
||||
style="flex-grow: 1; flex-shrink: 1; flex-basis: 0"
|
||||
v-bind:placeholder="$t('Ingredients')"></generic-multiselect>
|
||||
<b-input-group-append >
|
||||
<b-input-group-text >
|
||||
<b-input-group-append>
|
||||
<b-input-group-text>
|
||||
<b-form-checkbox v-model="search_foods_or" name="check-button" @change="refreshData"
|
||||
class="shadow-none" switch>
|
||||
<span class="text-uppercase" v-if="search_foods_or">{{ $t('or') }}</span>
|
||||
@ -105,10 +106,11 @@
|
||||
<b-input-group style="margin-top: 1vh">
|
||||
<generic-multiselect @change="genericSelectChanged" parent_variable="search_books"
|
||||
:initial_selection="search_books"
|
||||
search_function="listRecipeBooks" label="name" style="flex-grow: 1; flex-shrink: 1; flex-basis: 0"
|
||||
search_function="listRecipeBooks" label="name"
|
||||
style="flex-grow: 1; flex-shrink: 1; flex-basis: 0"
|
||||
v-bind:placeholder="$t('Books')"></generic-multiselect>
|
||||
<b-input-group-append >
|
||||
<b-input-group-text >
|
||||
<b-input-group-append>
|
||||
<b-input-group-text>
|
||||
|
||||
<b-form-checkbox v-model="search_books_or" name="check-button" @change="refreshData"
|
||||
class="shadow-none" tyle="width: 100%" switch>
|
||||
@ -139,6 +141,21 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row" style="margin-top: 2vh">
|
||||
<div class="col col-md-12">
|
||||
<b-pagination
|
||||
v-model="pagination_page"
|
||||
:total-rows="pagination_count"
|
||||
per-page="25"
|
||||
@change="pageChange"
|
||||
align="center">
|
||||
|
||||
</b-pagination>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
<div class="col-md-2 d-none d-md-block">
|
||||
|
||||
@ -185,6 +202,8 @@ export default {
|
||||
|
||||
advanced_search_visible: true,
|
||||
|
||||
pagination_count: 0,
|
||||
pagination_page: 1,
|
||||
}
|
||||
|
||||
},
|
||||
@ -213,10 +232,11 @@ export default {
|
||||
books_or: this.search_books_or,
|
||||
|
||||
internal: this.search_internal,
|
||||
limit: 20,
|
||||
page: this.pagination_page,
|
||||
}
|
||||
}).then(result => {
|
||||
this.recipes = result.data
|
||||
this.recipes = result.data.results
|
||||
this.pagination_count = result.data.count
|
||||
})
|
||||
},
|
||||
genericSelectChanged: function (obj) {
|
||||
@ -230,6 +250,10 @@ export default {
|
||||
this.search_foods = []
|
||||
this.search_books = []
|
||||
this.refreshData()
|
||||
},
|
||||
pageChange: function (page){
|
||||
this.pagination_page = page
|
||||
this.refreshData()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user