From beb4aa634f205bfb94187d790f917693e3115366 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Sat, 20 Feb 2021 23:42:44 +0100 Subject: [PATCH] forms --- cookbook/forms.py | 85 ++++++++++++++++++++++++----- cookbook/helper/scope_middleware.py | 4 +- cookbook/views/data.py | 4 +- cookbook/views/edit.py | 45 ++++++++------- cookbook/views/import_export.py | 6 +- cookbook/views/new.py | 9 +-- cookbook/views/views.py | 2 +- 7 files changed, 107 insertions(+), 48 deletions(-) diff --git a/cookbook/forms.py b/cookbook/forms.py index 6d8d5dba4..1e68f42c6 100644 --- a/cookbook/forms.py +++ b/cookbook/forms.py @@ -6,7 +6,7 @@ from emoji_picker.widgets import EmojiPickerTextInput from .models import (Comment, Food, InviteLink, Keyword, MealPlan, Recipe, RecipeBook, RecipeBookEntry, Storage, Sync, Unit, User, - UserPreference) + UserPreference, SupermarketCategory, MealType) class SelectWidget(widgets.Select): @@ -77,11 +77,16 @@ class ExternalRecipeForm(forms.ModelForm): file_path = forms.CharField(disabled=True, required=False) file_uid = forms.CharField(disabled=True, required=False) + def __init__(self, *args, **kwargs): + space = kwargs.pop('space') + super().__init__(*args, **kwargs) + self.fields['keywords'].queryset = Keyword.objects.filter(space=space).all() + class Meta: model = Recipe fields = ( 'name', 'description', 'servings', 'working_time', 'waiting_time', - 'file_path', 'file_uid' + 'file_path', 'file_uid', 'keywords' ) labels = { @@ -92,7 +97,10 @@ class ExternalRecipeForm(forms.ModelForm): 'file_path': _('Path'), 'file_uid': _('Storage UID'), } - # widgets = {'keywords': MultiSelectWidget} + widgets = {'keywords': MultiSelectWidget} + field_classes = { + 'keywords': SafeModelMultipleChoiceField, + } class ImportExportBase(forms.Form): @@ -114,12 +122,12 @@ class ImportForm(ImportExportBase): class ExportForm(ImportExportBase): - recipes = forms.ModelMultipleChoiceField(widget=MultiSelectWidget, queryset=None) + recipes = forms.ModelMultipleChoiceField(widget=MultiSelectWidget, queryset=Recipe.objects.none()) def __init__(self, *args, **kwargs): - super().__init__() - user = kwargs.pop('user') - self.fields['recipes'].queryset = Recipe.objects.filter(internal=True).filter(space=user.userpreference.space).all() + space = kwargs.pop('space') + super().__init__(*args, **kwargs) + self.fields['recipes'].queryset = Recipe.objects.filter(space=space).all() class UnitMergeForm(forms.Form): @@ -138,8 +146,12 @@ class UnitMergeForm(forms.Form): help_text=_('Unit that should be replaced.'), ) + def __init__(self, *args, **kwargs): + space = kwargs.pop('space') + super().__init__(*args, **kwargs) + self.fields['new_unit'].queryset = Unit.objects.filter(space=space).all() + self.fields['old_unit'].queryset = Unit.objects.filter(space=space).all() -# todo spaces form here on class FoodMergeForm(forms.Form): prefix = 'food' @@ -157,6 +169,12 @@ class FoodMergeForm(forms.Form): help_text=_('Food that should be replaced.'), ) + def __init__(self, *args, **kwargs): + space = kwargs.pop('space') + super().__init__(*args, **kwargs) + self.fields['new_food'].queryset = Food.objects.filter(space=space).all() + self.fields['old_food'].queryset = Food.objects.filter(space=space).all() + class CommentForm(forms.ModelForm): prefix = 'comment' @@ -181,6 +199,13 @@ class KeywordForm(forms.ModelForm): class FoodForm(forms.ModelForm): + + def __init__(self, *args, **kwargs): + space = kwargs.pop('space') + super().__init__(*args, **kwargs) + self.fields['recipe'].queryset = Recipe.objects.filter(space=space).all() + self.fields['supermarket_category'].queryset = SupermarketCategory.objects.filter(space=space).all() + class Meta: model = Food fields = ('name', 'description', 'ignore_shopping', 'recipe', 'supermarket_category') @@ -198,18 +223,16 @@ class StorageForm(forms.ModelForm): required=False ) password = forms.CharField( - widget=forms.TextInput( - attrs={'autocomplete': 'new-password', 'type': 'password'} - ), + widget=forms.TextInput(attrs={'autocomplete': 'new-password', 'type': 'password'}), required=False, - help_text=_('Leave empty for dropbox and enter app password for nextcloud.') # noqa: E501 + help_text=_('Leave empty for dropbox and enter app password for nextcloud.') ) token = forms.CharField( widget=forms.TextInput( attrs={'autocomplete': 'new-password', 'type': 'password'} ), required=False, - help_text=_('Leave empty for nextcloud and enter api token for dropbox.') # noqa: E501 + help_text=_('Leave empty for nextcloud and enter api token for dropbox.') ) class Meta: @@ -217,13 +240,18 @@ class StorageForm(forms.ModelForm): fields = ('name', 'method', 'username', 'password', 'token', 'url', 'path') help_texts = { - 'url': _('Leave empty for dropbox and enter only base url for nextcloud (/remote.php/webdav/ is added automatically)'), # noqa: E501 + 'url': _('Leave empty for dropbox and enter only base url for nextcloud (/remote.php/webdav/ is added automatically)'), } class RecipeBookEntryForm(forms.ModelForm): prefix = 'bookmark' + def __init__(self, *args, **kwargs): + space = kwargs.pop('space') + super().__init__(*args, **kwargs) + self.fields['book'].queryset = RecipeBook.objects.filter(space=space).all() + class Meta: model = RecipeBookEntry fields = ('book',) @@ -234,6 +262,12 @@ class RecipeBookEntryForm(forms.ModelForm): class SyncForm(forms.ModelForm): + + def __init__(self, *args, **kwargs): + space = kwargs.pop('space') + super().__init__(*args, **kwargs) + self.fields['book'].queryset = Storage.objects.filter(space=space).all() + class Meta: model = Sync fields = ('storage', 'path', 'active') @@ -246,13 +280,23 @@ class SyncForm(forms.ModelForm): class BatchEditForm(forms.Form): search = forms.CharField(label=_('Search String')) keywords = forms.ModelMultipleChoiceField( - queryset=Keyword.objects.none().order_by('id'), + queryset=Keyword.objects.none(), required=False, widget=MultiSelectWidget ) + def __init__(self, *args, **kwargs): + space = kwargs.pop('space') + super().__init__(*args, **kwargs) + self.fields['keywords'].queryset = Keyword.objects.filter(space=space).all().order_by('id') + class ImportRecipeForm(forms.ModelForm): + def __init__(self, *args, **kwargs): + space = kwargs.pop('space') + super().__init__(*args, **kwargs) + self.fields['keywords'].queryset = Keyword.objects.filter(space=space).all() + class Meta: model = Recipe fields = ('name', 'keywords', 'file_path', 'file_uid') @@ -270,6 +314,11 @@ class ImportRecipeForm(forms.ModelForm): class RecipeBookForm(forms.ModelForm): + def __init__(self, *args, **kwargs): + space = kwargs.pop('space') + super().__init__(*args, **kwargs) + self.fields['shared'].queryset = User.objects.filter(userpreference__space=space).all() + class Meta: model = RecipeBook fields = ('name', 'icon', 'description', 'shared') @@ -280,6 +329,12 @@ class RecipeBookForm(forms.ModelForm): class MealPlanForm(forms.ModelForm): + def __init__(self, *args, **kwargs): + space = kwargs.pop('space') + super().__init__(*args, **kwargs) + self.fields['recipe'].queryset = Recipe.objects.filter(space=space).all() + self.fields['meal_type'].queryset = MealType.objects.filter(space=space).all() + self.fields['shared'].queryset = User.objects.filter(userpreference__space=space).all() def clean(self): cleaned_data = super(MealPlanForm, self).clean() diff --git a/cookbook/helper/scope_middleware.py b/cookbook/helper/scope_middleware.py index 0bf415b8b..2ec472f49 100644 --- a/cookbook/helper/scope_middleware.py +++ b/cookbook/helper/scope_middleware.py @@ -9,8 +9,8 @@ class ScopeMiddleware: if request.user.is_authenticated: request.space = request.user.userpreference.space - #with scopes_disabled(): - with scope(space=request.space): + with scopes_disabled(): + #with scope(space=request.space): return self.get_response(request) else: return self.get_response(request) diff --git a/cookbook/views/data.py b/cookbook/views/data.py index 77081e5f9..39218e6fb 100644 --- a/cookbook/views/data.py +++ b/cookbook/views/data.py @@ -73,7 +73,7 @@ def batch_import(request): @group_required('user') def batch_edit(request): if request.method == "POST": - form = BatchEditForm(request.POST) + form = BatchEditForm(request.POST, space=request.space) if form.is_valid(): word = form.cleaned_data['search'] keywords = form.cleaned_data['keywords'] @@ -100,7 +100,7 @@ def batch_edit(request): return redirect('data_batch_edit') else: - form = BatchEditForm() + form = BatchEditForm(space=request.space) return render(request, 'batch/edit.html', {'form': form}) diff --git a/cookbook/views/edit.py b/cookbook/views/edit.py index e1913a9a8..3ce02087c 100644 --- a/cookbook/views/edit.py +++ b/cookbook/views/edit.py @@ -6,6 +6,7 @@ from django.shortcuts import get_object_or_404, render from django.urls import reverse, reverse_lazy from django.utils.translation import gettext as _ from django.views.generic import UpdateView +from django.views.generic.edit import FormMixin from django_scopes import scopes_disabled from cookbook.forms import (CommentForm, ExternalRecipeForm, FoodForm, @@ -51,7 +52,15 @@ def internal_recipe_update(request, pk): ) -class SyncUpdate(GroupRequiredMixin, UpdateView): +class SpaceFormMixing(FormMixin): + + def get_form_kwargs(self): + kwargs = super().get_form_kwargs() + kwargs.update({'space': self.request.space}) + return kwargs + + +class SyncUpdate(GroupRequiredMixin, UpdateView, SpaceFormMixing): groups_required = ['admin'] template_name = "generic/edit_template.html" model = Sync @@ -85,7 +94,7 @@ class KeywordUpdate(GroupRequiredMixin, UpdateView): return context -class FoodUpdate(GroupRequiredMixin, UpdateView): +class FoodUpdate(GroupRequiredMixin, UpdateView, SpaceFormMixing): groups_required = ['user'] template_name = "generic/edit_template.html" model = Food @@ -182,7 +191,7 @@ class ImportUpdate(GroupRequiredMixin, UpdateView): return context -class RecipeBookUpdate(OwnerRequiredMixin, UpdateView): +class RecipeBookUpdate(OwnerRequiredMixin, UpdateView, SpaceFormMixing): template_name = "generic/edit_template.html" model = RecipeBook form_class = RecipeBookForm @@ -196,7 +205,7 @@ class RecipeBookUpdate(OwnerRequiredMixin, UpdateView): return context -class MealPlanUpdate(OwnerRequiredMixin, UpdateView): +class MealPlanUpdate(OwnerRequiredMixin, UpdateView, SpaceFormMixing): template_name = "generic/edit_template.html" model = MealPlan form_class = MealPlanForm @@ -216,7 +225,7 @@ class MealPlanUpdate(OwnerRequiredMixin, UpdateView): return context -class ExternalRecipeUpdate(GroupRequiredMixin, UpdateView): +class ExternalRecipeUpdate(GroupRequiredMixin, UpdateView, SpaceFormMixing): groups_required = ['user'] model = Recipe form_class = ExternalRecipeForm @@ -226,8 +235,8 @@ class ExternalRecipeUpdate(GroupRequiredMixin, UpdateView): self.object = form.save(commit=False) old_recipe = Recipe.objects.get(pk=self.object.pk, space=self.request.space) if not old_recipe.name == self.object.name: + # TODO central location to handle storage type switches if self.object.storage.method == Storage.DROPBOX: - # TODO central location to handle storage type switches Dropbox.rename_file(old_recipe, self.object.name) if self.object.storage.method == Storage.NEXTCLOUD: Nextcloud.rename_file(old_recipe, self.object.name) @@ -240,24 +249,18 @@ class ExternalRecipeUpdate(GroupRequiredMixin, UpdateView): os.path.splitext(self.object.file_path)[1] ) - messages.add_message( - self.request, messages.SUCCESS, _('Changes saved!') - ) + messages.add_message(self.request, messages.SUCCESS, _('Changes saved!')) return super(ExternalRecipeUpdate, self).form_valid(form) def form_invalid(self, form): - messages.add_message( - self.request, - messages.ERROR, - _('Error saving changes!') - ) + messages.add_message(self.request, messages.ERROR, _('Error saving changes!')) return super(ExternalRecipeUpdate, self).form_valid(form) def get_success_url(self): return reverse('edit_recipe', kwargs={'pk': self.object.pk}) def get_context_data(self, **kwargs): - context = super(ExternalRecipeUpdate, self).get_context_data(**kwargs) + context = super().get_context_data(**kwargs) context['title'] = _("Recipe") context['view_url'] = reverse('view_recipe', args=[self.object.pk]) if self.object.storage: @@ -271,7 +274,7 @@ class ExternalRecipeUpdate(GroupRequiredMixin, UpdateView): def edit_ingredients(request): if request.method == "POST": success = False - units_form = UnitMergeForm(request.POST, prefix=UnitMergeForm.prefix) + units_form = UnitMergeForm(request.POST, prefix=UnitMergeForm.prefix, space=request.space) if units_form.is_valid(): new_unit = units_form.cleaned_data['new_unit'] old_unit = units_form.cleaned_data['old_unit'] @@ -287,7 +290,7 @@ def edit_ingredients(request): else: messages.add_message(request, messages.ERROR, _('Cannot merge with the same object!')) - food_form = FoodMergeForm(request.POST, prefix=FoodMergeForm.prefix) + food_form = FoodMergeForm(request.POST, prefix=FoodMergeForm.prefix, space=request.space) if food_form.is_valid(): new_food = food_form.cleaned_data['new_food'] old_food = food_form.cleaned_data['old_food'] @@ -304,10 +307,10 @@ def edit_ingredients(request): messages.add_message(request, messages.ERROR, _('Cannot merge with the same object!')) if success: - units_form = UnitMergeForm() - food_form = FoodMergeForm() + units_form = UnitMergeForm(space=request.space) + food_form = FoodMergeForm(space=request.space) else: - units_form = UnitMergeForm() - food_form = FoodMergeForm() + units_form = UnitMergeForm(space=request.space) + food_form = FoodMergeForm(space=request.space) return render(request, 'forms/ingredients.html', {'units_form': units_form, 'food_form': food_form}) diff --git a/cookbook/views/import_export.py b/cookbook/views/import_export.py index d7ea9de02..bf3f7c761 100644 --- a/cookbook/views/import_export.py +++ b/cookbook/views/import_export.py @@ -49,7 +49,7 @@ def import_recipe(request): @group_required('user') def export_recipe(request): if request.method == "POST": - form = ExportForm(request.POST, user=request.user) + form = ExportForm(request.POST, space=request.space) if form.is_valid(): try: integration = get_integration(request, form.cleaned_data['type']) @@ -58,11 +58,11 @@ def export_recipe(request): messages.add_message(request, messages.ERROR, _('Exporting is not implemented for this provider')) else: - form = ExportForm(user=request.user) + form = ExportForm(space=request.space) recipe = request.GET.get('r') if recipe: if re.match(r'^([0-9])+$', recipe): if recipe := Recipe.objects.filter(pk=int(recipe), space=request.space).first(): - form = ExportForm(initial={'recipes': recipe}, user=request.user) + form = ExportForm(initial={'recipes': recipe}, space=request.space) return render(request, 'export.html', {'form': form}) diff --git a/cookbook/views/new.py b/cookbook/views/new.py index bdc2bac76..16acb9921 100644 --- a/cookbook/views/new.py +++ b/cookbook/views/new.py @@ -14,6 +14,7 @@ from cookbook.helper.permission_helper import (GroupRequiredMixin, group_required) from cookbook.models import (InviteLink, Keyword, MealPlan, MealType, Recipe, RecipeBook, RecipeImport, ShareLink, Step) +from cookbook.views.edit import SpaceFormMixing class RecipeCreate(GroupRequiredMixin, CreateView): @@ -89,7 +90,7 @@ class StorageCreate(GroupRequiredMixin, CreateView): @group_required('user') def create_new_external_recipe(request, import_id): if request.method == "POST": - form = ImportRecipeForm(request.POST) + form = ImportRecipeForm(request.POST, space=request.space) if form.is_valid(): new_recipe = get_object_or_404(RecipeImport, pk=import_id, space=request.space) recipe = Recipe() @@ -117,13 +118,13 @@ def create_new_external_recipe(request, import_id): 'file_path': new_recipe.file_path, 'name': new_recipe.name, 'file_uid': new_recipe.file_uid - } + }, space=request.space ) return render(request, 'forms/edit_import_recipe.html', {'form': form}) -class RecipeBookCreate(GroupRequiredMixin, CreateView): +class RecipeBookCreate(GroupRequiredMixin, CreateView, SpaceFormMixing): groups_required = ['user'] template_name = "generic/new_template.html" model = RecipeBook @@ -143,7 +144,7 @@ class RecipeBookCreate(GroupRequiredMixin, CreateView): return context -class MealPlanCreate(GroupRequiredMixin, CreateView): +class MealPlanCreate(GroupRequiredMixin, CreateView, SpaceFormMixing): groups_required = ['user'] template_name = "generic/new_template.html" model = MealPlan diff --git a/cookbook/views/views.py b/cookbook/views/views.py index a20da69ca..d08e9a19c 100644 --- a/cookbook/views/views.py +++ b/cookbook/views/views.py @@ -129,7 +129,7 @@ def recipe_view(request, pk, share=None): request, messages.SUCCESS, _('Comment saved!') ) - bookmark_form = RecipeBookEntryForm(request.POST, prefix='bookmark') + bookmark_form = RecipeBookEntryForm(request.POST, prefix='bookmark', space=request.space) if bookmark_form.is_valid(): bookmark = RecipeBookEntry() bookmark.recipe = recipe