keyword update, tests sqlite and PG
This commit is contained in:
parent
2f91c2f86e
commit
2da0f5c478
@ -18,8 +18,6 @@ from .models import (Comment, CookLog, Food, Ingredient, InviteLink, Keyword,
|
|||||||
|
|
||||||
from cookbook.managers import DICTIONARY
|
from cookbook.managers import DICTIONARY
|
||||||
|
|
||||||
from cookbook.managers import DICTIONARY
|
|
||||||
|
|
||||||
|
|
||||||
class CustomUserAdmin(UserAdmin):
|
class CustomUserAdmin(UserAdmin):
|
||||||
def has_add_permission(self, request, obj=None):
|
def has_add_permission(self, request, obj=None):
|
||||||
|
@ -117,7 +117,7 @@ def search_recipes(request, queryset, params):
|
|||||||
)
|
)
|
||||||
queryset = queryset.filter(query_filter).annotate(rank=search_rank)
|
queryset = queryset.filter(query_filter).annotate(rank=search_rank)
|
||||||
else:
|
else:
|
||||||
queryset = queryset.filter(name__icontains=search_string)
|
queryset = queryset.filter(query_filter)
|
||||||
|
|
||||||
if len(search_keywords) > 0:
|
if len(search_keywords) > 0:
|
||||||
if search_keywords_or == 'true':
|
if search_keywords_or == 'true':
|
||||||
|
@ -52,7 +52,7 @@ class Chowdown(Integration):
|
|||||||
|
|
||||||
for k in tags.split(','):
|
for k in tags.split(','):
|
||||||
print(f'adding keyword {k.strip()}')
|
print(f'adding keyword {k.strip()}')
|
||||||
keyword, created = Keyword.get_or_create(name=k.strip(), space=self.request.space)
|
keyword, created = Keyword.objects.get_or_create(name=k.strip(), space=self.request.space)
|
||||||
recipe.keywords.add(keyword)
|
recipe.keywords.add(keyword)
|
||||||
|
|
||||||
step = Step.objects.create(
|
step = Step.objects.create(
|
||||||
|
@ -16,7 +16,7 @@ from django_scopes import scope
|
|||||||
from cookbook.forms import ImportExportBase
|
from cookbook.forms import ImportExportBase
|
||||||
from cookbook.helper.image_processing import get_filetype
|
from cookbook.helper.image_processing import get_filetype
|
||||||
from cookbook.models import Keyword, Recipe
|
from cookbook.models import Keyword, Recipe
|
||||||
from recipes.settings import DEBUG
|
from recipes.settings import DATABASES, DEBUG
|
||||||
|
|
||||||
|
|
||||||
class Integration:
|
class Integration:
|
||||||
@ -33,8 +33,29 @@ class Integration:
|
|||||||
"""
|
"""
|
||||||
self.request = request
|
self.request = request
|
||||||
self.export_type = export_type
|
self.export_type = export_type
|
||||||
# TODO add all import keywords under the importer root node
|
name = f'Import {export_type}'
|
||||||
self.keyword = Keyword.objects.first()
|
description = f'Imported by {request.user.get_user_name()} at {date_format(datetime.datetime.now(), "DATETIME_FORMAT")}. Type: {export_type}'
|
||||||
|
icon = '📥'
|
||||||
|
count = Keyword.objects.filter(name__icontains=name, space=request.space).count()
|
||||||
|
if count != 0:
|
||||||
|
pk = Keyword.objects.filter(name__icontains=name, space=request.space).order_by('id').first().id
|
||||||
|
name = name + " " + str(pk)
|
||||||
|
|
||||||
|
if DATABASES['default']['ENGINE'] in ['django.db.backends.postgresql_psycopg2', 'django.db.backends.postgresql']:
|
||||||
|
parent = Keyword.objects.get_or_create(name='Import', space=request.space)
|
||||||
|
parent.add_child(
|
||||||
|
name=name,
|
||||||
|
description=description,
|
||||||
|
icon=icon,
|
||||||
|
space=request.space
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self.keyword = Keyword.objects.create(
|
||||||
|
name=name,
|
||||||
|
description=description,
|
||||||
|
icon=icon,
|
||||||
|
space=request.space
|
||||||
|
)
|
||||||
|
|
||||||
def do_export(self, recipes):
|
def do_export(self, recipes):
|
||||||
"""
|
"""
|
||||||
@ -181,7 +202,7 @@ class Integration:
|
|||||||
except BadZipFile:
|
except BadZipFile:
|
||||||
il.msg += 'ERROR ' + _(
|
il.msg += 'ERROR ' + _(
|
||||||
'Importer expected a .zip file. Did you choose the correct importer type for your data ?') + '\n'
|
'Importer expected a .zip file. Did you choose the correct importer type for your data ?') + '\n'
|
||||||
except:
|
except Exception as e:
|
||||||
msg = 'ERROR ' + _(
|
msg = 'ERROR ' + _(
|
||||||
'An unexpected error occurred during the import. Please make sure you have uploaded a valid file.') + '\n'
|
'An unexpected error occurred during the import. Please make sure you have uploaded a valid file.') + '\n'
|
||||||
self.handle_exception(e, log=il, message=msg)
|
self.handle_exception(e, log=il, message=msg)
|
||||||
|
@ -27,7 +27,7 @@ def set_default_search_vector(apps, schema_editor):
|
|||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('cookbook', '0141_keyword_to_tree'),
|
('cookbook', '0141_auto_20210713_1042'),
|
||||||
]
|
]
|
||||||
operations = [
|
operations = [
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
|
@ -19,7 +19,7 @@ from django.utils.translation import gettext as _
|
|||||||
from treebeard.mp_tree import MP_Node, MP_NodeManager
|
from treebeard.mp_tree import MP_Node, MP_NodeManager
|
||||||
from django_scopes import ScopedManager, scopes_disabled
|
from django_scopes import ScopedManager, scopes_disabled
|
||||||
from django_prometheus.models import ExportModelOperationsMixin
|
from django_prometheus.models import ExportModelOperationsMixin
|
||||||
from recipes.settings import (COMMENT_PREF_DEFAULT, FRACTION_PREF_DEFAULT,
|
from recipes.settings import (COMMENT_PREF_DEFAULT, DATABASES, FRACTION_PREF_DEFAULT,
|
||||||
STICKY_NAV_PREF_DEFAULT)
|
STICKY_NAV_PREF_DEFAULT)
|
||||||
|
|
||||||
|
|
||||||
@ -37,8 +37,20 @@ def get_model_name(model):
|
|||||||
return ('_'.join(re.findall('[A-Z][^A-Z]*', model.__name__))).lower()
|
return ('_'.join(re.findall('[A-Z][^A-Z]*', model.__name__))).lower()
|
||||||
|
|
||||||
|
|
||||||
class PermissionModelMixin:
|
class TreeManager(MP_NodeManager):
|
||||||
|
def get_or_create(self, **kwargs):
|
||||||
|
# model.Manager get_or_create() is not compatible with MP_Tree
|
||||||
|
kwargs['name'] = kwargs['name'].strip()
|
||||||
|
q = self.filter(name__iexact=kwargs['name'], space=kwargs['space'])
|
||||||
|
if len(q) != 0:
|
||||||
|
return q[0], False
|
||||||
|
else:
|
||||||
|
with scopes_disabled():
|
||||||
|
node = self.model.add_root(**kwargs)
|
||||||
|
return node, True
|
||||||
|
|
||||||
|
|
||||||
|
class PermissionModelMixin:
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_space_key():
|
def get_space_key():
|
||||||
return ('space',)
|
return ('space',)
|
||||||
@ -265,7 +277,6 @@ class SyncLog(models.Model, PermissionModelMixin):
|
|||||||
|
|
||||||
|
|
||||||
class Keyword(ExportModelOperationsMixin('keyword'), MP_Node, PermissionModelMixin):
|
class Keyword(ExportModelOperationsMixin('keyword'), MP_Node, PermissionModelMixin):
|
||||||
# TODO create get_or_create method
|
|
||||||
node_order_by = ['name']
|
node_order_by = ['name']
|
||||||
name = models.CharField(max_length=64)
|
name = models.CharField(max_length=64)
|
||||||
icon = models.CharField(max_length=16, blank=True, null=True)
|
icon = models.CharField(max_length=16, blank=True, null=True)
|
||||||
@ -274,7 +285,7 @@ class Keyword(ExportModelOperationsMixin('keyword'), MP_Node, PermissionModelMix
|
|||||||
updated_at = models.DateTimeField(auto_now=True)
|
updated_at = models.DateTimeField(auto_now=True)
|
||||||
|
|
||||||
space = models.ForeignKey(Space, on_delete=models.CASCADE)
|
space = models.ForeignKey(Space, on_delete=models.CASCADE)
|
||||||
objects = ScopedManager(space='space', _manager_class=MP_NodeManager)
|
objects = ScopedManager(space='space', _manager_class=TreeManager)
|
||||||
|
|
||||||
_full_name_separator = ' > '
|
_full_name_separator = ' > '
|
||||||
|
|
||||||
@ -291,19 +302,6 @@ class Keyword(ExportModelOperationsMixin('keyword'), MP_Node, PermissionModelMix
|
|||||||
return self.get_parent().id
|
return self.get_parent().id
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def get_or_create(self, **kwargs):
|
|
||||||
# an attempt to mimic get_or_create functionality with Keywords
|
|
||||||
# function attempts to get the keyword,
|
|
||||||
# if the length of the return is 0 will add a root node
|
|
||||||
kwargs['name'] = kwargs['name'].strip()
|
|
||||||
q = self.get_tree().filter(name=kwargs['name'], space=kwargs['space'])
|
|
||||||
if len(q) != 0:
|
|
||||||
return q[0], False
|
|
||||||
else:
|
|
||||||
kw = Keyword.add_root(**kwargs)
|
|
||||||
return kw, True
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def full_name(self):
|
def full_name(self):
|
||||||
"""
|
"""
|
||||||
@ -337,6 +335,7 @@ class Keyword(ExportModelOperationsMixin('keyword'), MP_Node, PermissionModelMix
|
|||||||
def get_num_children(self):
|
def get_num_children(self):
|
||||||
return self.get_children().count()
|
return self.get_children().count()
|
||||||
|
|
||||||
|
# use self.objects.get_or_create() instead
|
||||||
@classmethod
|
@classmethod
|
||||||
def add_root(self, **kwargs):
|
def add_root(self, **kwargs):
|
||||||
with scopes_disabled():
|
with scopes_disabled():
|
||||||
|
@ -224,7 +224,7 @@ class KeywordSerializer(UniqueFieldsMixin, serializers.ModelSerializer):
|
|||||||
# since multi select tags dont have id's
|
# since multi select tags dont have id's
|
||||||
# duplicate names might be routed to create
|
# duplicate names might be routed to create
|
||||||
validated_data['space'] = self.context['request'].space
|
validated_data['space'] = self.context['request'].space
|
||||||
obj, created = Keyword.get_or_create(**validated_data)
|
obj, created = Keyword.objects.get_or_create(**validated_data)
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
@ -1 +1 @@
|
|||||||
.shake[data-v-88855b04]{-webkit-animation:shake-data-v-88855b04 .82s cubic-bezier(.36,.07,.19,.97) both;animation:shake-data-v-88855b04 .82s cubic-bezier(.36,.07,.19,.97) both;transform:translateZ(0);-webkit-backface-visibility:hidden;backface-visibility:hidden;perspective:1000px}@-webkit-keyframes shake-data-v-88855b04{10%,90%{transform:translate3d(-1px,0,0)}20%,80%{transform:translate3d(2px,0,0)}30%,50%,70%{transform:translate3d(-4px,0,0)}40%,60%{transform:translate3d(4px,0,0)}}@keyframes shake-data-v-88855b04{10%,90%{transform:translate3d(-1px,0,0)}20%,80%{transform:translate3d(2px,0,0)}30%,50%,70%{transform:translate3d(-4px,0,0)}40%,60%{transform:translate3d(4px,0,0)}}
|
.shake[data-v-54d4941f]{-webkit-animation:shake-data-v-54d4941f .82s cubic-bezier(.36,.07,.19,.97) both;animation:shake-data-v-54d4941f .82s cubic-bezier(.36,.07,.19,.97) both;transform:translateZ(0);-webkit-backface-visibility:hidden;backface-visibility:hidden;perspective:1000px}@-webkit-keyframes shake-data-v-54d4941f{10%,90%{transform:translate3d(-1px,0,0)}20%,80%{transform:translate3d(2px,0,0)}30%,50%,70%{transform:translate3d(-4px,0,0)}40%,60%{transform:translate3d(4px,0,0)}}@keyframes shake-data-v-54d4941f{10%,90%{transform:translate3d(-1px,0,0)}20%,80%{transform:translate3d(2px,0,0)}30%,50%,70%{transform:translate3d(-4px,0,0)}40%,60%{transform:translate3d(4px,0,0)}}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -7,6 +7,15 @@ from django_scopes import scopes_disabled
|
|||||||
from cookbook.models import Keyword
|
from cookbook.models import Keyword
|
||||||
from cookbook.tests.conftest import get_random_recipe
|
from cookbook.tests.conftest import get_random_recipe
|
||||||
|
|
||||||
|
# ------------------ IMPORTANT -------------------
|
||||||
|
#
|
||||||
|
# if changing any capabilities associated with keywords
|
||||||
|
# you will need to ensure that it is tested against both
|
||||||
|
# SqlLite and PostgresSQL
|
||||||
|
# adding load_env() to settings.py will enable Postgress access
|
||||||
|
#
|
||||||
|
# ------------------ IMPORTANT -------------------
|
||||||
|
|
||||||
LIST_URL = 'api:keyword-list'
|
LIST_URL = 'api:keyword-list'
|
||||||
DETAIL_URL = 'api:keyword-detail'
|
DETAIL_URL = 'api:keyword-detail'
|
||||||
MOVE_URL = 'api:keyword-move'
|
MOVE_URL = 'api:keyword-move'
|
||||||
@ -16,7 +25,7 @@ MERGE_URL = 'api:keyword-merge'
|
|||||||
# TODO are there better ways to manage these fixtures?
|
# TODO are there better ways to manage these fixtures?
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
def obj_1(space_1):
|
def obj_1(space_1):
|
||||||
return Keyword.add_root(name='test_1', space=space_1)
|
return Keyword.objects.get_or_create(name='test_1', space=space_1)[0]
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
@ -31,12 +40,12 @@ def obj_1_1_1(obj_1_1, space_1):
|
|||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def obj_2(space_1):
|
def obj_2(space_1):
|
||||||
return Keyword.add_root(name='test_2', space=space_1)
|
return Keyword.objects.get_or_create(name='test_2', space=space_1)[0]
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
def obj_3(space_2):
|
def obj_3(space_2):
|
||||||
return Keyword.add_root(name='test_3', space=space_2)
|
return Keyword.objects.get_or_create(name='test_3', space=space_2)[0]
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
|
@ -332,7 +332,7 @@ class SupermarketCategoryRelationViewSet(viewsets.ModelViewSet, StandardFilterMi
|
|||||||
return super().get_queryset()
|
return super().get_queryset()
|
||||||
|
|
||||||
|
|
||||||
class KeywordViewSet(viewsets.ModelViewSet, StandardFilterMixin):
|
class KeywordViewSet(viewsets.ModelViewSet, TreeMixin):
|
||||||
queryset = Keyword.objects
|
queryset = Keyword.objects
|
||||||
model = Keyword
|
model = Keyword
|
||||||
serializer_class = KeywordSerializer
|
serializer_class = KeywordSerializer
|
||||||
@ -447,67 +447,6 @@ class RecipePagination(PageNumberPagination):
|
|||||||
max_page_size = 100
|
max_page_size = 100
|
||||||
|
|
||||||
|
|
||||||
# TODO move to separate class to cleanup
|
|
||||||
class RecipeSchema(AutoSchema):
|
|
||||||
|
|
||||||
def get_path_parameters(self, path, method):
|
|
||||||
if not is_list_view(path, method, self.view):
|
|
||||||
return super(RecipeSchema, self).get_path_parameters(path, method)
|
|
||||||
|
|
||||||
parameters = super().get_path_parameters(path, method)
|
|
||||||
parameters.append({
|
|
||||||
"name": 'query', "in": "query", "required": False,
|
|
||||||
"description": 'Query string matched (fuzzy) against recipe name. In the future also fulltext search.',
|
|
||||||
'schema': {'type': 'string', },
|
|
||||||
})
|
|
||||||
parameters.append({
|
|
||||||
"name": 'keywords', "in": "query", "required": False,
|
|
||||||
"description": 'Id of keyword a recipe should have. For multiple repeat parameter.',
|
|
||||||
'schema': {'type': 'string', },
|
|
||||||
})
|
|
||||||
parameters.append({
|
|
||||||
"name": 'foods', "in": "query", "required": False,
|
|
||||||
"description": 'Id of food a recipe should have. For multiple repeat parameter.',
|
|
||||||
'schema': {'type': 'string', },
|
|
||||||
})
|
|
||||||
parameters.append({
|
|
||||||
"name": 'books', "in": "query", "required": False,
|
|
||||||
"description": 'Id of book a recipe should have. For multiple repeat parameter.',
|
|
||||||
'schema': {'type': 'string', },
|
|
||||||
})
|
|
||||||
parameters.append({
|
|
||||||
"name": 'keywords_or', "in": "query", "required": False,
|
|
||||||
"description": 'If recipe should have all (AND) or any (OR) of the provided keywords.',
|
|
||||||
'schema': {'type': 'string', },
|
|
||||||
})
|
|
||||||
parameters.append({
|
|
||||||
"name": 'foods_or', "in": "query", "required": False,
|
|
||||||
"description": 'If recipe should have all (AND) or any (OR) any of the provided foods.',
|
|
||||||
'schema': {'type': 'string', },
|
|
||||||
})
|
|
||||||
parameters.append({
|
|
||||||
"name": 'books_or', "in": "query", "required": False,
|
|
||||||
"description": 'If recipe should be in all (AND) or any (OR) any of the provided books.',
|
|
||||||
'schema': {'type': 'string', },
|
|
||||||
})
|
|
||||||
parameters.append({
|
|
||||||
"name": 'internal', "in": "query", "required": False,
|
|
||||||
"description": 'true or false. If only internal recipes should be returned or not.',
|
|
||||||
'schema': {'type': 'string', },
|
|
||||||
})
|
|
||||||
parameters.append({
|
|
||||||
"name": 'random', "in": "query", "required": False,
|
|
||||||
"description": 'true or false. returns the results in randomized order.',
|
|
||||||
'schema': {'type': 'string', },
|
|
||||||
})
|
|
||||||
parameters.append({
|
|
||||||
"name": 'new', "in": "query", "required": False,
|
|
||||||
"description": 'true or false. returns new results first in search results',
|
|
||||||
'schema': {'type': 'string', },
|
|
||||||
})
|
|
||||||
return parameters
|
|
||||||
|
|
||||||
|
|
||||||
class RecipeViewSet(viewsets.ModelViewSet):
|
class RecipeViewSet(viewsets.ModelViewSet):
|
||||||
queryset = Recipe.objects
|
queryset = Recipe.objects
|
||||||
serializer_class = RecipeSerializer
|
serializer_class = RecipeSerializer
|
||||||
|
@ -148,14 +148,9 @@ def import_url(request):
|
|||||||
|
|
||||||
recipe.steps.add(step)
|
recipe.steps.add(step)
|
||||||
|
|
||||||
all_keywords = Keyword.get_tree()
|
|
||||||
for kw in data['keywords']:
|
for kw in data['keywords']:
|
||||||
q = all_keywords.filter(name=kw['text'], space=request.space)
|
k = Keyword.objects.get_or_create(name=kw['text'], space=request.space)
|
||||||
if len(q) != 0:
|
recipe.keywords.add(k)
|
||||||
recipe.keywords.add(q[0])
|
|
||||||
elif data['all_keywords']:
|
|
||||||
k = Keyword.add_root(name=kw['text'], space=request.space)
|
|
||||||
recipe.keywords.add(k)
|
|
||||||
|
|
||||||
for ing in data['recipeIngredient']:
|
for ing in data['recipeIngredient']:
|
||||||
ingredient = Ingredient(space=request.space,)
|
ingredient = Ingredient(space=request.space,)
|
||||||
|
@ -11,10 +11,8 @@ from django.contrib.auth.forms import PasswordChangeForm
|
|||||||
from django.contrib.auth.models import Group
|
from django.contrib.auth.models import Group
|
||||||
from django.contrib.auth.password_validation import validate_password
|
from django.contrib.auth.password_validation import validate_password
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.db.models import Avg, Q
|
from django.db.models import Avg, Q, Sum
|
||||||
from django.db.models import Sum
|
from django.http import HttpResponseRedirect, JsonResponse
|
||||||
from django.http import HttpResponseRedirect
|
|
||||||
from django.http import JsonResponse
|
|
||||||
from django.shortcuts import get_object_or_404, render, redirect
|
from django.shortcuts import get_object_or_404, render, redirect
|
||||||
from django.urls import reverse, reverse_lazy
|
from django.urls import reverse, reverse_lazy
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
@ -26,7 +24,8 @@ from rest_framework.authtoken.models import Token
|
|||||||
from cookbook.filters import RecipeFilter
|
from cookbook.filters import RecipeFilter
|
||||||
from cookbook.forms import (CommentForm, Recipe, User,
|
from cookbook.forms import (CommentForm, Recipe, User,
|
||||||
UserCreateForm, UserNameForm, UserPreference,
|
UserCreateForm, UserNameForm, UserPreference,
|
||||||
UserPreferenceForm, SpaceJoinForm, SpaceCreateForm, SearchPreferenceForm)
|
UserPreferenceForm, SpaceJoinForm, SpaceCreateForm,
|
||||||
|
SearchPreferenceForm, AllAuthSignupForm)
|
||||||
from cookbook.helper.ingredient_parser import parse
|
from cookbook.helper.ingredient_parser import parse
|
||||||
from cookbook.helper.permission_helper import group_required, share_link_valid, has_group_permission
|
from cookbook.helper.permission_helper import group_required, share_link_valid, has_group_permission
|
||||||
from cookbook.models import (Comment, CookLog, InviteLink, MealPlan,
|
from cookbook.models import (Comment, CookLog, InviteLink, MealPlan,
|
||||||
|
@ -19,7 +19,7 @@ from django.contrib.staticfiles.storage import staticfiles_storage
|
|||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
from webpack_loader.loader import WebpackLoader
|
from webpack_loader.loader import WebpackLoader
|
||||||
load_dotenv()
|
# load_dotenv()
|
||||||
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
|
||||||
# Get vars from .env files
|
# Get vars from .env files
|
||||||
@ -279,6 +279,16 @@ else:
|
|||||||
# }
|
# }
|
||||||
# }
|
# }
|
||||||
|
|
||||||
|
# SQLite testing DB
|
||||||
|
DATABASES = {
|
||||||
|
'default': {
|
||||||
|
'ENGINE': 'django.db.backends.sqlite3',
|
||||||
|
'OPTIONS': ast.literal_eval(os.getenv('DB_OPTIONS')) if os.getenv('DB_OPTIONS') else {},
|
||||||
|
'NAME': 'db.sqlite3',
|
||||||
|
'CONN_MAX_AGE': 600,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CACHES = {
|
CACHES = {
|
||||||
'default': {
|
'default': {
|
||||||
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
|
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
|
||||||
|
@ -453,7 +453,7 @@ export default {
|
|||||||
|
|
||||||
apiClient.listRecipes(
|
apiClient.listRecipes(
|
||||||
undefined, keyword, undefined, undefined, undefined, undefined,
|
undefined, keyword, undefined, undefined, undefined, undefined,
|
||||||
undefined, undefined, undefined, undefined, pageSize
|
undefined, undefined, undefined, undefined, undefined, pageSize, undefined
|
||||||
).then(result => {
|
).then(result => {
|
||||||
if (col == 'left') {
|
if (col == 'left') {
|
||||||
parent = this.findKeyword(this.keywords, kw.id)
|
parent = this.findKeyword(this.keywords, kw.id)
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<div row>
|
<div row>
|
||||||
<b-card no-body d-flex flex-column :class="{'border border-primary' : over, 'shake': isError}"
|
<b-card no-body d-flex flex-column :class="{'border border-primary' : over, 'shake': isError}"
|
||||||
refs="keywordCard"
|
refs="keywordCard"
|
||||||
style="height: 10vh;" :style="{'cursor:grab' : draggle}"
|
style="height: 10vh;" :style="{'cursor:grab' : draggable}"
|
||||||
@dragover.prevent
|
@dragover.prevent
|
||||||
@dragenter.prevent
|
@dragenter.prevent
|
||||||
:draggable="draggable"
|
:draggable="draggable"
|
||||||
|
@ -97,7 +97,6 @@
|
|||||||
"merge_confirmation": "Replace {source} with {target}",
|
"merge_confirmation": "Replace {source} with {target}",
|
||||||
"move_selection": "Select a parent to move {child} to.",
|
"move_selection": "Select a parent to move {child} to.",
|
||||||
"merge_selection": "Replace all occurences of {source} with the selected {type}.",
|
"merge_selection": "Replace all occurences of {source} with the selected {type}.",
|
||||||
"Advanced Search Settings": "Advanced Search Settings",
|
|
||||||
"Download": "Download",
|
"Download": "Download",
|
||||||
"Root": "Root"
|
"Root": "Root"
|
||||||
}
|
}
|
||||||
|
@ -4193,13 +4193,12 @@ export const ApiApiAxiosParamCreator = function (configuration?: Configuration)
|
|||||||
* @param {string} [booksOr] If recipe should be in all (AND) or any (OR) any of the provided books.
|
* @param {string} [booksOr] If recipe should be in all (AND) or any (OR) any of the provided books.
|
||||||
* @param {string} [internal] true or false. If only internal recipes should be returned or not.
|
* @param {string} [internal] true or false. If only internal recipes should be returned or not.
|
||||||
* @param {string} [random] true or false. returns the results in randomized order.
|
* @param {string} [random] true or false. returns the results in randomized order.
|
||||||
* @param {string} [_new] true or false. returns new results first in search results
|
|
||||||
* @param {number} [page] A page number within the paginated result set.
|
* @param {number} [page] A page number within the paginated result set.
|
||||||
* @param {number} [pageSize] Number of results to return per page.
|
* @param {number} [pageSize] Number of results to return per page.
|
||||||
* @param {*} [options] Override http request option.
|
* @param {*} [options] Override http request option.
|
||||||
* @throws {RequiredError}
|
* @throws {RequiredError}
|
||||||
*/
|
*/
|
||||||
listRecipes: async (query?: string, keywords?: string, foods?: string, books?: string, keywordsOr?: string, foodsOr?: string, booksOr?: string, internal?: string, random?: string, _new?: string, page?: number, pageSize?: number, options: any = {}): Promise<RequestArgs> => {
|
listRecipes: async (query?: string, keywords?: string, foods?: string, books?: string, keywordsOr?: string, foodsOr?: string, booksOr?: string, internal?: string, random?: string, page?: number, pageSize?: number, options: any = {}): Promise<RequestArgs> => {
|
||||||
const localVarPath = `/api/recipe/`;
|
const localVarPath = `/api/recipe/`;
|
||||||
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
||||||
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
|
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
|
||||||
@ -4248,10 +4247,6 @@ export const ApiApiAxiosParamCreator = function (configuration?: Configuration)
|
|||||||
localVarQueryParameter['random'] = random;
|
localVarQueryParameter['random'] = random;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_new !== undefined) {
|
|
||||||
localVarQueryParameter['new'] = _new;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (page !== undefined) {
|
if (page !== undefined) {
|
||||||
localVarQueryParameter['page'] = page;
|
localVarQueryParameter['page'] = page;
|
||||||
}
|
}
|
||||||
@ -8076,14 +8071,13 @@ export const ApiApiFp = function(configuration?: Configuration) {
|
|||||||
* @param {string} [booksOr] If recipe should be in all (AND) or any (OR) any of the provided books.
|
* @param {string} [booksOr] If recipe should be in all (AND) or any (OR) any of the provided books.
|
||||||
* @param {string} [internal] true or false. If only internal recipes should be returned or not.
|
* @param {string} [internal] true or false. If only internal recipes should be returned or not.
|
||||||
* @param {string} [random] true or false. returns the results in randomized order.
|
* @param {string} [random] true or false. returns the results in randomized order.
|
||||||
* @param {string} [_new] true or false. returns new results first in search results
|
|
||||||
* @param {number} [page] A page number within the paginated result set.
|
* @param {number} [page] A page number within the paginated result set.
|
||||||
* @param {number} [pageSize] Number of results to return per page.
|
* @param {number} [pageSize] Number of results to return per page.
|
||||||
* @param {*} [options] Override http request option.
|
* @param {*} [options] Override http request option.
|
||||||
* @throws {RequiredError}
|
* @throws {RequiredError}
|
||||||
*/
|
*/
|
||||||
async listRecipes(query?: string, keywords?: string, foods?: string, books?: string, keywordsOr?: string, foodsOr?: string, booksOr?: string, internal?: string, random?: string, _new?: string, page?: number, pageSize?: number, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<InlineResponse200>> {
|
async listRecipes(query?: string, keywords?: string, foods?: string, books?: string, keywordsOr?: string, foodsOr?: string, booksOr?: string, internal?: string, random?: string, page?: number, pageSize?: number, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<InlineResponse2001>> {
|
||||||
const localVarAxiosArgs = await localVarAxiosParamCreator.listRecipes(query, keywords, foods, books, keywordsOr, foodsOr, booksOr, internal, random, _new, page, pageSize, options);
|
const localVarAxiosArgs = await localVarAxiosParamCreator.listRecipes(query, keywords, foods, books, keywordsOr, foodsOr, booksOr, internal, random, page, pageSize, options);
|
||||||
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
@ -9590,14 +9584,13 @@ export const ApiApiFactory = function (configuration?: Configuration, basePath?:
|
|||||||
* @param {string} [booksOr] If recipe should be in all (AND) or any (OR) any of the provided books.
|
* @param {string} [booksOr] If recipe should be in all (AND) or any (OR) any of the provided books.
|
||||||
* @param {string} [internal] true or false. If only internal recipes should be returned or not.
|
* @param {string} [internal] true or false. If only internal recipes should be returned or not.
|
||||||
* @param {string} [random] true or false. returns the results in randomized order.
|
* @param {string} [random] true or false. returns the results in randomized order.
|
||||||
* @param {string} [_new] true or false. returns new results first in search results
|
|
||||||
* @param {number} [page] A page number within the paginated result set.
|
* @param {number} [page] A page number within the paginated result set.
|
||||||
* @param {number} [pageSize] Number of results to return per page.
|
* @param {number} [pageSize] Number of results to return per page.
|
||||||
* @param {*} [options] Override http request option.
|
* @param {*} [options] Override http request option.
|
||||||
* @throws {RequiredError}
|
* @throws {RequiredError}
|
||||||
*/
|
*/
|
||||||
listRecipes(query?: string, keywords?: string, foods?: string, books?: string, keywordsOr?: string, foodsOr?: string, booksOr?: string, internal?: string, random?: string, _new?: string, page?: number, pageSize?: number, options?: any): AxiosPromise<InlineResponse200> {
|
listRecipes(query?: string, keywords?: string, foods?: string, books?: string, keywordsOr?: string, foodsOr?: string, booksOr?: string, internal?: string, random?: string, page?: number, pageSize?: number, options?: any): AxiosPromise<InlineResponse2001> {
|
||||||
return localVarFp.listRecipes(query, keywords, foods, books, keywordsOr, foodsOr, booksOr, internal, random, _new, page, pageSize, options).then((request) => request(axios, basePath));
|
return localVarFp.listRecipes(query, keywords, foods, books, keywordsOr, foodsOr, booksOr, internal, random, page, pageSize, options).then((request) => request(axios, basePath));
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -11130,15 +11123,14 @@ export class ApiApi extends BaseAPI {
|
|||||||
* @param {string} [booksOr] If recipe should be in all (AND) or any (OR) any of the provided books.
|
* @param {string} [booksOr] If recipe should be in all (AND) or any (OR) any of the provided books.
|
||||||
* @param {string} [internal] true or false. If only internal recipes should be returned or not.
|
* @param {string} [internal] true or false. If only internal recipes should be returned or not.
|
||||||
* @param {string} [random] true or false. returns the results in randomized order.
|
* @param {string} [random] true or false. returns the results in randomized order.
|
||||||
* @param {string} [_new] true or false. returns new results first in search results
|
|
||||||
* @param {number} [page] A page number within the paginated result set.
|
* @param {number} [page] A page number within the paginated result set.
|
||||||
* @param {number} [pageSize] Number of results to return per page.
|
* @param {number} [pageSize] Number of results to return per page.
|
||||||
* @param {*} [options] Override http request option.
|
* @param {*} [options] Override http request option.
|
||||||
* @throws {RequiredError}
|
* @throws {RequiredError}
|
||||||
* @memberof ApiApi
|
* @memberof ApiApi
|
||||||
*/
|
*/
|
||||||
public listRecipes(query?: string, keywords?: string, foods?: string, books?: string, keywordsOr?: string, foodsOr?: string, booksOr?: string, internal?: string, random?: string, _new?: string, page?: number, pageSize?: number, options?: any) {
|
public listRecipes(query?: string, keywords?: string, foods?: string, books?: string, keywordsOr?: string, foodsOr?: string, booksOr?: string, internal?: string, random?: string, page?: number, pageSize?: number, options?: any) {
|
||||||
return ApiApiFp(this.configuration).listRecipes(query, keywords, foods, books, keywordsOr, foodsOr, booksOr, internal, random, _new, page, pageSize, options).then((request) => request(this.axios, this.basePath));
|
return ApiApiFp(this.configuration).listRecipes(query, keywords, foods, books, keywordsOr, foodsOr, booksOr, internal, random, page, pageSize, options).then((request) => request(this.axios, this.basePath));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user