diff --git a/cookbook/admin.py b/cookbook/admin.py index 61966eb0..b47afd92 100644 --- a/cookbook/admin.py +++ b/cookbook/admin.py @@ -10,13 +10,13 @@ from treebeard.forms import movenodeform_factory from cookbook.managers import DICTIONARY -from .models import (Automation, BookmarkletImport, Comment, CookLog, Food, FoodInheritField, - ImportLog, Ingredient, InviteLink, Keyword, MealPlan, MealType, - NutritionInformation, Property, PropertyType, Recipe, RecipeBook, - RecipeBookEntry, RecipeImport, SearchPreference, ShareLink, ShoppingList, - ShoppingListEntry, ShoppingListRecipe, Space, Step, Storage, Supermarket, - SupermarketCategory, SupermarketCategoryRelation, Sync, SyncLog, TelegramBot, - Unit, UnitConversion, UserFile, UserPreference, UserSpace, ViewLog) +from .models import (BookmarkletImport, Comment, CookLog, Food, ImportLog, Ingredient, InviteLink, + Keyword, MealPlan, MealType, NutritionInformation, Property, PropertyType, + Recipe, RecipeBook, RecipeBookEntry, RecipeImport, SearchPreference, ShareLink, + ShoppingList, ShoppingListEntry, ShoppingListRecipe, Space, Step, Storage, + Supermarket, SupermarketCategory, SupermarketCategoryRelation, Sync, SyncLog, + TelegramBot, Unit, UnitConversion, UserFile, UserPreference, UserSpace, + ViewLog) class CustomUserAdmin(UserAdmin): diff --git a/cookbook/managers.py b/cookbook/managers.py index 5bfc60e4..09f4bd58 100644 --- a/cookbook/managers.py +++ b/cookbook/managers.py @@ -34,35 +34,14 @@ class RecipeSearchManager(models.Manager): + SearchVector(StringAgg('steps__ingredients__food__name__unaccent', delimiter=' '), weight='B', config=language) + SearchVector(StringAgg('keywords__name__unaccent', delimiter=' '), weight='B', config=language)) search_rank = SearchRank(search_vectors, search_query) - # USING TRIGRAM BREAKS WEB SEARCH - # ADDING MULTIPLE TRIGRAMS CREATES DUPLICATE RESULTS - # DISTINCT NOT COMPAITBLE WITH ANNOTATE - # trigram_name = (TrigramSimilarity('name', search_text)) - # trigram_description = (TrigramSimilarity('description', search_text)) - # trigram_food = (TrigramSimilarity('steps__ingredients__food__name', search_text)) - # trigram_keyword = (TrigramSimilarity('keywords__name', search_text)) - # adding additional trigrams created duplicates - # + TrigramSimilarity('description', search_text) - # + TrigramSimilarity('steps__ingredients__food__name', search_text) - # + TrigramSimilarity('keywords__name', search_text) + return ( self.get_queryset() .annotate( search=search_vectors, rank=search_rank, - # trigram=trigram_name+trigram_description+trigram_food+trigram_keyword - # trigram_name=trigram_name, - # trigram_description=trigram_description, - # trigram_food=trigram_food, - # trigram_keyword=trigram_keyword ) .filter( Q(search=search_query) - # | Q(trigram_name__gt=0.1) - # | Q(name__icontains=search_text) - # | Q(trigram_name__gt=0.2) - # | Q(trigram_description__gt=0.2) - # | Q(trigram_food__gt=0.2) - # | Q(trigram_keyword__gt=0.2) ) .order_by('-rank')) diff --git a/cookbook/schemas.py b/cookbook/schemas.py index 36ce6655..e465de45 100644 --- a/cookbook/schemas.py +++ b/cookbook/schemas.py @@ -67,17 +67,3 @@ class FilterSchema(AutoSchema): 'schema': {'type': 'string', }, }) return parameters - - -# class QueryOnlySchema(AutoSchema): -# def get_path_parameters(self, path, method): -# if not is_list_view(path, method, self.view): -# return super(QueryOnlySchema, 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 object name.', -# 'schema': {'type': 'string', }, -# }) -# return parameters diff --git a/cookbook/serializer.py b/cookbook/serializer.py index 9a496271..44e6832b 100644 --- a/cookbook/serializer.py +++ b/cookbook/serializer.py @@ -570,7 +570,6 @@ class FoodSimpleSerializer(serializers.ModelSerializer): class FoodSerializer(UniqueFieldsMixin, WritableNestedModelSerializer, ExtendedRecipeMixin, OpenDataModelMixin): supermarket_category = SupermarketCategorySerializer(allow_null=True, required=False) recipe = RecipeSimpleSerializer(allow_null=True, required=False) - # shopping = serializers.SerializerMethodField('get_shopping_status') shopping = serializers.ReadOnlyField(source='shopping_status') inherit_fields = FoodInheritFieldSerializer(many=True, allow_null=True, required=False) child_inherit_fields = FoodInheritFieldSerializer(many=True, allow_null=True, required=False) @@ -609,9 +608,6 @@ class FoodSerializer(UniqueFieldsMixin, WritableNestedModelSerializer, ExtendedR filter |= Q(path__startswith=obj.path, depth__gt=obj.depth) return Food.objects.filter(filter).filter(onhand_users__id__in=shared_users).exists() - # def get_shopping_status(self, obj): - # return ShoppingListEntry.objects.filter(space=obj.space, food=obj, checked=False).count() > 0 - def create(self, validated_data): name = validated_data['name'].strip() diff --git a/cookbook/signals.py b/cookbook/signals.py index f50f0701..4636ca8a 100644 --- a/cookbook/signals.py +++ b/cookbook/signals.py @@ -1,4 +1,3 @@ -from decimal import Decimal from functools import wraps from django.conf import settings @@ -13,8 +12,8 @@ from django_scopes import scope, scopes_disabled from cookbook.helper.cache_helper import CacheHelper from cookbook.helper.shopping_helper import RecipeShoppingEditor from cookbook.managers import DICTIONARY -from cookbook.models import (Food, FoodInheritField, Ingredient, MealPlan, Recipe, - ShoppingListEntry, Step, UserPreference, SearchPreference, SearchFields, Unit, PropertyType) +from cookbook.models import (Food, MealPlan, PropertyType, Recipe, SearchFields, SearchPreference, + Step, Unit, UserPreference) SQLITE = True if settings.DATABASES['default']['ENGINE'] in ['django.db.backends.postgresql_psycopg2', diff --git a/cookbook/tables.py b/cookbook/tables.py index 4fa1a731..6392f791 100644 --- a/cookbook/tables.py +++ b/cookbook/tables.py @@ -3,8 +3,7 @@ from django.utils.html import format_html from django.utils.translation import gettext as _ from django_tables2.utils import A -from .models import (CookLog, InviteLink, Recipe, RecipeImport, - Storage, Sync, SyncLog, ViewLog) +from .models import CookLog, InviteLink, RecipeImport, Storage, Sync, SyncLog, ViewLog class StorageTable(tables.Table): diff --git a/cookbook/views/api.py b/cookbook/views/api.py index 9b3c1a7d..24b0bdf1 100644 --- a/cookbook/views/api.py +++ b/cookbook/views/api.py @@ -1490,7 +1490,6 @@ class ImportOpenData(APIView): # TODO validate data print(request.data) selected_version = request.data['selected_version'] - selected_datatypes = request.data['selected_datatypes'] update_existing = str2bool(request.data['update_existing']) use_metric = str2bool(request.data['use_metric']) diff --git a/cookbook/views/data.py b/cookbook/views/data.py index 7511617a..0c272478 100644 --- a/cookbook/views/data.py +++ b/cookbook/views/data.py @@ -10,12 +10,11 @@ from django.utils.translation import gettext as _ from django.utils.translation import ngettext from django_tables2 import RequestConfig from oauth2_provider.models import AccessToken -from rest_framework.authtoken.models import Token from cookbook.forms import BatchEditForm, SyncForm -from cookbook.helper.permission_helper import group_required, has_group_permission, above_space_limit -from cookbook.models import (Comment, Food, Keyword, Recipe, RecipeImport, Sync, - Unit, UserPreference, BookmarkletImport) +from cookbook.helper.permission_helper import (above_space_limit, group_required, + has_group_permission) +from cookbook.models import BookmarkletImport, Recipe, RecipeImport, Sync from cookbook.tables import SyncTable from recipes import settings @@ -119,11 +118,19 @@ def import_url(request): return HttpResponseRedirect(reverse('index')) if (api_token := AccessToken.objects.filter(user=request.user, scope='bookmarklet').first()) is None: - api_token = AccessToken.objects.create(user=request.user, scope='bookmarklet', expires=(timezone.now() + timezone.timedelta(days=365*10)), token=f'tda_{str(uuid.uuid4()).replace("-","_")}') + api_token = AccessToken.objects.create( + user=request.user, + scope='bookmarklet', + expires=( + timezone.now() + + timezone.timedelta( + days=365 * + 10)), + token=f'tda_{str(uuid.uuid4()).replace("-","_")}') bookmarklet_import_id = -1 if 'id' in request.GET: if bookmarklet_import := BookmarkletImport.objects.filter(id=request.GET['id']).first(): bookmarklet_import_id = bookmarklet_import.pk - return render(request, 'url_import.html', {'api_token': api_token, 'bookmarklet_import_id': bookmarklet_import_id}) \ No newline at end of file + return render(request, 'url_import.html', {'api_token': api_token, 'bookmarklet_import_id': bookmarklet_import_id}) diff --git a/cookbook/views/delete.py b/cookbook/views/delete.py index eefe6f38..411eb323 100644 --- a/cookbook/views/delete.py +++ b/cookbook/views/delete.py @@ -9,7 +9,7 @@ from django.views.generic import DeleteView from cookbook.helper.permission_helper import GroupRequiredMixin, OwnerRequiredMixin, group_required from cookbook.models import (Comment, InviteLink, MealPlan, Recipe, RecipeBook, RecipeBookEntry, - RecipeImport, Storage, Sync, UserSpace, Space) + RecipeImport, Space, Storage, Sync, UserSpace) from cookbook.provider.dropbox import Dropbox from cookbook.provider.local import Local from cookbook.provider.nextcloud import Nextcloud @@ -99,18 +99,6 @@ class SyncDelete(GroupRequiredMixin, DeleteView): return context -# class KeywordDelete(GroupRequiredMixin, DeleteView): -# groups_required = ['user'] -# template_name = "generic/delete_template.html" -# model = Keyword -# success_url = reverse_lazy('list_keyword') - -# def get_context_data(self, **kwargs): -# context = super(KeywordDelete, self).get_context_data(**kwargs) -# context['title'] = _("Keyword") -# return context - - class StorageDelete(GroupRequiredMixin, DeleteView): groups_required = ['admin'] template_name = "generic/delete_template.html" diff --git a/cookbook/views/edit.py b/cookbook/views/edit.py index 1bacc54a..1726b2b5 100644 --- a/cookbook/views/edit.py +++ b/cookbook/views/edit.py @@ -9,9 +9,9 @@ from django.views.generic import UpdateView from django.views.generic.edit import FormMixin from cookbook.forms import CommentForm, ExternalRecipeForm, StorageForm, SyncForm -from cookbook.helper.permission_helper import GroupRequiredMixin, OwnerRequiredMixin, group_required, above_space_limit -from cookbook.models import (Comment, MealPlan, MealType, Recipe, RecipeImport, Storage, Sync, - UserPreference) +from cookbook.helper.permission_helper import (GroupRequiredMixin, OwnerRequiredMixin, + above_space_limit, group_required) +from cookbook.models import Comment, Recipe, RecipeImport, Storage, Sync from cookbook.provider.dropbox import Dropbox from cookbook.provider.local import Local from cookbook.provider.nextcloud import Nextcloud @@ -74,40 +74,6 @@ class SyncUpdate(GroupRequiredMixin, UpdateView, SpaceFormMixing): return context -# class KeywordUpdate(GroupRequiredMixin, UpdateView): -# groups_required = ['user'] -# template_name = "generic/edit_template.html" -# model = Keyword -# form_class = KeywordForm - -# # TODO add msg box - -# def get_success_url(self): -# return reverse('list_keyword') - -# def get_context_data(self, **kwargs): -# context = super().get_context_data(**kwargs) -# context['title'] = _("Keyword") -# return context - - -# class FoodUpdate(GroupRequiredMixin, UpdateView, SpaceFormMixing): -# groups_required = ['user'] -# template_name = "generic/edit_template.html" -# model = Food -# form_class = FoodForm - -# # TODO add msg box - -# def get_success_url(self): -# return reverse('edit_food', kwargs={'pk': self.object.pk}) - -# def get_context_data(self, **kwargs): -# context = super(FoodUpdate, self).get_context_data(**kwargs) -# context['title'] = _("Food") -# return context - - @group_required('admin') def edit_storage(request, pk): instance = get_object_or_404(Storage, pk=pk, space=request.space) diff --git a/cookbook/views/lists.py b/cookbook/views/lists.py index 8c24d8a5..b9ef9cc7 100644 --- a/cookbook/views/lists.py +++ b/cookbook/views/lists.py @@ -7,8 +7,7 @@ from django_tables2 import RequestConfig from cookbook.helper.permission_helper import group_required from cookbook.models import InviteLink, RecipeImport, Storage, SyncLog, UserFile -from cookbook.tables import (ImportLogTable, InviteLinkTable, RecipeImportTable, - StorageTable) +from cookbook.tables import ImportLogTable, InviteLinkTable, RecipeImportTable, StorageTable @group_required('admin') @@ -196,7 +195,7 @@ def custom_filter(request): def user_file(request): try: current_file_size_mb = UserFile.objects.filter(space=request.space).aggregate(Sum('file_size_kb'))[ - 'file_size_kb__sum'] / 1000 + 'file_size_kb__sum'] / 1000 except TypeError: current_file_size_mb = 0 diff --git a/cookbook/views/new.py b/cookbook/views/new.py index 48dcf99d..d4368f67 100644 --- a/cookbook/views/new.py +++ b/cookbook/views/new.py @@ -1,22 +1,14 @@ -import re -from datetime import datetime, timedelta -from html import escape -from smtplib import SMTPException from django.contrib import messages -from django.contrib.auth.models import Group -from django.core.mail import BadHeaderError, send_mail from django.http import HttpResponseRedirect from django.shortcuts import get_object_or_404, redirect, render from django.urls import reverse, reverse_lazy from django.utils.translation import gettext as _ from django.views.generic import CreateView -from cookbook.forms import ImportRecipeForm, InviteLinkForm, Storage, StorageForm -from cookbook.helper.permission_helper import GroupRequiredMixin, group_required, above_space_limit -from cookbook.models import (InviteLink, MealPlan, MealType, Recipe, RecipeBook, RecipeImport, - ShareLink, Step, UserPreference, UserSpace) -from cookbook.views.edit import SpaceFormMixing +from cookbook.forms import ImportRecipeForm, Storage, StorageForm +from cookbook.helper.permission_helper import GroupRequiredMixin, above_space_limit, group_required +from cookbook.models import Recipe, RecipeImport, ShareLink, Step from recipes import settings @@ -56,24 +48,6 @@ def share_link(request, pk): return HttpResponseRedirect(reverse('view_recipe', kwargs={'pk': pk, 'share': link.uuid})) -# class KeywordCreate(GroupRequiredMixin, CreateView): -# groups_required = ['user'] -# template_name = "generic/new_template.html" -# model = Keyword -# form_class = KeywordForm -# success_url = reverse_lazy('list_keyword') - -# def form_valid(self, form): -# form.cleaned_data['space'] = self.request.space -# form.save() -# return HttpResponseRedirect(reverse('list_keyword')) - -# def get_context_data(self, **kwargs): -# context = super(KeywordCreate, self).get_context_data(**kwargs) -# context['title'] = _("Keyword") -# return context - - class StorageCreate(GroupRequiredMixin, CreateView): groups_required = ['admin'] template_name = "generic/new_template.html" @@ -133,5 +107,3 @@ def create_new_external_recipe(request, import_id): ) return render(request, 'forms/edit_import_recipe.html', {'form': form}) - - diff --git a/cookbook/views/telegram.py b/cookbook/views/telegram.py index 43c4b5d0..9cde6d7c 100644 --- a/cookbook/views/telegram.py +++ b/cookbook/views/telegram.py @@ -2,14 +2,13 @@ import json import traceback import requests -from django.db.models import Q from django.http import JsonResponse from django.shortcuts import get_object_or_404 from django.views.decorators.csrf import csrf_exempt from cookbook.helper.ingredient_parser import IngredientParser from cookbook.helper.permission_helper import group_required -from cookbook.models import ShoppingList, ShoppingListEntry, TelegramBot +from cookbook.models import ShoppingListEntry, TelegramBot @group_required('user') @@ -21,7 +20,8 @@ def setup_bot(request, pk): create_response = requests.get(f'https://api.telegram.org/bot{bot.token}/setWebhook?url={hook_url}') info_response = requests.get(f'https://api.telegram.org/bot{bot.token}/getWebhookInfo') - return JsonResponse({'hook_url': hook_url, 'create_response': json.loads(create_response.content.decode()), 'info_response': json.loads(info_response.content.decode())}, json_dumps_params={'indent': 4}) + return JsonResponse({'hook_url': hook_url, 'create_response': json.loads(create_response.content.decode()), + 'info_response': json.loads(info_response.content.decode())}, json_dumps_params={'indent': 4}) @group_required('user') @@ -31,7 +31,8 @@ def remove_bot(request, pk): remove_response = requests.get(f'https://api.telegram.org/bot{bot.token}/deleteWebhook') info_response = requests.get(f'https://api.telegram.org/bot{bot.token}/getWebhookInfo') - return JsonResponse({'remove_response': json.loads(remove_response.content.decode()), 'info_response': json.loads(info_response.content.decode())}, json_dumps_params={'indent': 4}) + return JsonResponse({'remove_response': json.loads(remove_response.content.decode()), + 'info_response': json.loads(info_response.content.decode())}, json_dumps_params={'indent': 4}) @csrf_exempt diff --git a/recipes/middleware.py b/recipes/middleware.py index 8f608794..737fec29 100644 --- a/recipes/middleware.py +++ b/recipes/middleware.py @@ -1,4 +1,3 @@ -import time from os import getenv from django.conf import settings @@ -31,12 +30,12 @@ def terminal_width(): s = struct.pack('HHHH', 0, 0, 0, 0) x = fcntl.ioctl(1, termios.TIOCGWINSZ, s) width = struct.unpack('HHHH', x)[1] - except: + except Exception: pass if width <= 0: try: width = int(getenv['COLUMNS']) - except: + except Exception: pass if width <= 0: width = 80 diff --git a/recipes/urls.py b/recipes/urls.py index 660cbd2e..9d251c10 100644 --- a/recipes/urls.py +++ b/recipes/urls.py @@ -52,7 +52,7 @@ for p in settings.PLUGINS: if settings.DEBUG: print(e.msg) print(f'ERROR failed loading plugin <{p["name"]}> urls, did you forget creating urls.py in your plugin?') - except Exception as e: + except Exception: if settings.DEBUG: print(f'ERROR failed loading urls for plugin <{p["name"]}>') traceback.format_exc()