diff --git a/cookbook/forms.py b/cookbook/forms.py
index 1e5dee36..18a67d6d 100644
--- a/cookbook/forms.py
+++ b/cookbook/forms.py
@@ -10,20 +10,19 @@ from django_scopes import scopes_disabled
from django_scopes.forms import SafeModelChoiceField, SafeModelMultipleChoiceField
from hcaptcha.fields import hCaptchaField
-
-
-from .models import (Comment, Food, InviteLink, Keyword, Recipe, RecipeBook, RecipeBookEntry,
- SearchPreference, Space, Storage, Sync, User, UserPreference, ConnectorConfig)
+from .models import Comment, Food, InviteLink, Keyword, Recipe, RecipeBook, RecipeBookEntry, SearchPreference, Space, Storage, Sync, User, UserPreference, ConnectorConfig
class SelectWidget(widgets.Select):
+
class Media:
- js = ('custom/js/form_select.js',)
+ js = ('custom/js/form_select.js', )
class MultiSelectWidget(widgets.SelectMultiple):
+
class Media:
- js = ('custom/js/form_multiselect.js',)
+ js = ('custom/js/form_multiselect.js', )
# Yes there are some stupid browsers that still dont support this but
@@ -43,9 +42,7 @@ class UserNameForm(forms.ModelForm):
model = User
fields = ('first_name', 'last_name')
- help_texts = {
- 'first_name': _('Both fields are optional. If none are given the username will be displayed instead')
- }
+ help_texts = {'first_name': _('Both fields are optional. If none are given the username will be displayed instead')}
class ExternalRecipeForm(forms.ModelForm):
@@ -59,23 +56,14 @@ class ExternalRecipeForm(forms.ModelForm):
class Meta:
model = Recipe
- fields = (
- 'name', 'description', 'servings', 'working_time', 'waiting_time',
- 'file_path', 'file_uid', 'keywords'
- )
+ fields = ('name', 'description', 'servings', 'working_time', 'waiting_time', 'file_path', 'file_uid', 'keywords')
labels = {
- 'name': _('Name'),
- 'keywords': _('Keywords'),
- 'working_time': _('Preparation time in minutes'),
- 'waiting_time': _('Waiting time (cooking/baking) in minutes'),
- 'file_path': _('Path'),
- 'file_uid': _('Storage UID'),
+ 'name': _('Name'), 'keywords': _('Keywords'), 'working_time': _('Preparation time in minutes'), 'waiting_time': _('Waiting time (cooking/baking) in minutes'),
+ 'file_path': _('Path'), 'file_uid': _('Storage UID'),
}
widgets = {'keywords': MultiSelectWidget}
- field_classes = {
- 'keywords': SafeModelMultipleChoiceField,
- }
+ field_classes = {'keywords': SafeModelMultipleChoiceField, }
class ImportExportBase(forms.Form):
@@ -102,14 +90,11 @@ class ImportExportBase(forms.Form):
REZEPTSUITEDE = 'REZEPTSUITEDE'
PDF = 'PDF'
- type = forms.ChoiceField(choices=(
- (DEFAULT, _('Default')), (PAPRIKA, 'Paprika'), (NEXTCLOUD, 'Nextcloud Cookbook'),
- (MEALIE, 'Mealie'), (CHOWDOWN, 'Chowdown'), (SAFFRON, 'Saffron'), (CHEFTAP, 'ChefTap'),
- (PEPPERPLATE, 'Pepperplate'), (RECETTETEK, 'RecetteTek'), (RECIPESAGE, 'Recipe Sage'), (DOMESTICA, 'Domestica'),
- (MEALMASTER, 'MealMaster'), (REZKONV, 'RezKonv'), (OPENEATS, 'Openeats'), (RECIPEKEEPER, 'Recipe Keeper'),
- (PLANTOEAT, 'Plantoeat'), (COOKBOOKAPP, 'CookBookApp'), (COPYMETHAT, 'CopyMeThat'), (PDF, 'PDF'), (MELARECIPES, 'Melarecipes'),
- (COOKMATE, 'Cookmate'), (REZEPTSUITEDE, 'Recipesuite.de')
- ))
+ type = forms.ChoiceField(choices=((DEFAULT, _('Default')), (PAPRIKA, 'Paprika'), (NEXTCLOUD, 'Nextcloud Cookbook'), (MEALIE, 'Mealie'), (CHOWDOWN, 'Chowdown'),
+ (SAFFRON, 'Saffron'), (CHEFTAP, 'ChefTap'), (PEPPERPLATE, 'Pepperplate'), (RECETTETEK, 'RecetteTek'), (RECIPESAGE, 'Recipe Sage'),
+ (DOMESTICA, 'Domestica'), (MEALMASTER, 'MealMaster'), (REZKONV, 'RezKonv'), (OPENEATS, 'Openeats'), (RECIPEKEEPER, 'Recipe Keeper'),
+ (PLANTOEAT, 'Plantoeat'), (COOKBOOKAPP, 'CookBookApp'), (COPYMETHAT, 'CopyMeThat'), (PDF, 'PDF'), (MELARECIPES, 'Melarecipes'),
+ (COOKMATE, 'Cookmate'), (REZEPTSUITEDE, 'Recipesuite.de')))
class MultipleFileInput(forms.ClearableFileInput):
@@ -117,6 +102,7 @@ class MultipleFileInput(forms.ClearableFileInput):
class MultipleFileField(forms.FileField):
+
def __init__(self, *args, **kwargs):
kwargs.setdefault("widget", MultipleFileInput())
super().__init__(*args, **kwargs)
@@ -132,9 +118,8 @@ class MultipleFileField(forms.FileField):
class ImportForm(ImportExportBase):
files = MultipleFileField(required=True)
- duplicates = forms.BooleanField(help_text=_(
- 'To prevent duplicates recipes with the same name as existing ones are ignored. Check this box to import everything.'),
- required=False)
+ duplicates = forms.BooleanField(help_text=_('To prevent duplicates recipes with the same name as existing ones are ignored. Check this box to import everything.'),
+ required=False)
class ExportForm(ImportExportBase):
@@ -153,42 +138,26 @@ class CommentForm(forms.ModelForm):
class Meta:
model = Comment
- fields = ('text',)
+ fields = ('text', )
- labels = {
- 'text': _('Add your comment: '),
- }
- widgets = {
- 'text': forms.Textarea(attrs={'rows': 2, 'cols': 15}),
- }
+ labels = {'text': _('Add your comment: '), }
+ widgets = {'text': forms.Textarea(attrs={'rows': 2, 'cols': 15}), }
class StorageForm(forms.ModelForm):
- username = forms.CharField(
- widget=forms.TextInput(attrs={'autocomplete': 'new-password'}),
- required=False
- )
- password = forms.CharField(
- widget=forms.TextInput(attrs={'autocomplete': 'new-password', 'type': 'password'}),
- required=False,
- 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.')
- )
+ username = forms.CharField(widget=forms.TextInput(attrs={'autocomplete': 'new-password'}), required=False)
+ password = forms.CharField(widget=forms.TextInput(attrs={'autocomplete': 'new-password', 'type': 'password'}),
+ required=False,
+ 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.'))
class Meta:
model = Storage
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)'),
- }
+ help_texts = {'url': _('Leave empty for dropbox and enter only base url for nextcloud (/remote.php/webdav/
is added automatically)'), }
class ConnectorConfigForm(forms.ModelForm):
@@ -237,21 +206,21 @@ class ConnectorConfigForm(forms.ModelForm):
# TODO: Deprecate
-class RecipeBookEntryForm(forms.ModelForm):
- prefix = 'bookmark'
+# 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()
+# 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',)
+# class Meta:
+# model = RecipeBookEntry
+# fields = ('book',)
- field_classes = {
- 'book': SafeModelChoiceField,
- }
+# field_classes = {
+# 'book': SafeModelChoiceField,
+# }
class SyncForm(forms.ModelForm):
@@ -265,25 +234,15 @@ class SyncForm(forms.ModelForm):
model = Sync
fields = ('storage', 'path', 'active')
- field_classes = {
- 'storage': SafeModelChoiceField,
- }
+ field_classes = {'storage': SafeModelChoiceField, }
- labels = {
- 'storage': _('Storage'),
- 'path': _('Path'),
- 'active': _('Active')
- }
+ labels = {'storage': _('Storage'), 'path': _('Path'), 'active': _('Active')}
# TODO deprecate
class BatchEditForm(forms.Form):
search = forms.CharField(label=_('Search String'))
- keywords = forms.ModelMultipleChoiceField(
- queryset=Keyword.objects.none(),
- required=False,
- widget=MultiSelectWidget
- )
+ keywords = forms.ModelMultipleChoiceField(queryset=Keyword.objects.none(), required=False, widget=MultiSelectWidget)
def __init__(self, *args, **kwargs):
space = kwargs.pop('space')
@@ -292,6 +251,7 @@ class BatchEditForm(forms.Form):
class ImportRecipeForm(forms.ModelForm):
+
def __init__(self, *args, **kwargs):
space = kwargs.pop('space')
super().__init__(*args, **kwargs)
@@ -301,19 +261,13 @@ class ImportRecipeForm(forms.ModelForm):
model = Recipe
fields = ('name', 'keywords', 'file_path', 'file_uid')
- labels = {
- 'name': _('Name'),
- 'keywords': _('Keywords'),
- 'file_path': _('Path'),
- 'file_uid': _('File ID'),
- }
+ labels = {'name': _('Name'), 'keywords': _('Keywords'), 'file_path': _('Path'), 'file_uid': _('File ID'), }
widgets = {'keywords': MultiSelectWidget}
- field_classes = {
- 'keywords': SafeModelChoiceField,
- }
+ field_classes = {'keywords': SafeModelChoiceField, }
class InviteLinkForm(forms.ModelForm):
+
def __init__(self, *args, **kwargs):
user = kwargs.pop('user')
super().__init__(*args, **kwargs)
@@ -321,8 +275,8 @@ class InviteLinkForm(forms.ModelForm):
def clean(self):
space = self.cleaned_data['space']
- if space.max_users != 0 and (UserPreference.objects.filter(space=space).count() +
- InviteLink.objects.filter(valid_until__gte=datetime.today(), used_by=None, space=space).count()) >= space.max_users:
+ if space.max_users != 0 and (UserPreference.objects.filter(space=space).count()
+ + InviteLink.objects.filter(valid_until__gte=datetime.today(), used_by=None, space=space).count()) >= space.max_users:
raise ValidationError(_('Maximum number of users for this space reached.'))
def clean_email(self):
@@ -336,12 +290,8 @@ class InviteLinkForm(forms.ModelForm):
class Meta:
model = InviteLink
fields = ('email', 'group', 'valid_until', 'space')
- help_texts = {
- 'email': _('An email address is not required but if present the invite link will be sent to the user.'),
- }
- field_classes = {
- 'space': SafeModelChoiceField,
- }
+ help_texts = {'email': _('An email address is not required but if present the invite link will be sent to the user.'), }
+ field_classes = {'space': SafeModelChoiceField, }
class SpaceCreateForm(forms.Form):
@@ -387,133 +337,109 @@ class CustomPasswordResetForm(ResetPasswordForm):
class UserCreateForm(forms.Form):
name = forms.CharField(label='Username')
- password = forms.CharField(
- widget=forms.TextInput(
- attrs={'autocomplete': 'new-password', 'type': 'password'}
- )
- )
- password_confirm = forms.CharField(
- widget=forms.TextInput(
- attrs={'autocomplete': 'new-password', 'type': 'password'}
- )
- )
+ password = forms.CharField(widget=forms.TextInput(attrs={'autocomplete': 'new-password', 'type': 'password'}))
+ password_confirm = forms.CharField(widget=forms.TextInput(attrs={'autocomplete': 'new-password', 'type': 'password'}))
class SearchPreferenceForm(forms.ModelForm):
prefix = 'search'
- trigram_threshold = forms.DecimalField(min_value=0.01, max_value=1, decimal_places=2,
+ trigram_threshold = forms.DecimalField(min_value=0.01,
+ max_value=1,
+ decimal_places=2,
widget=NumberInput(attrs={'class': "form-control-range", 'type': 'range'}),
- help_text=_(
- 'Determines how fuzzy a search is if it uses trigram similarity matching (e.g. low values mean more typos are ignored).'))
+ help_text=_('Determines how fuzzy a search is if it uses trigram similarity matching (e.g. low values mean more typos are ignored).'))
preset = forms.CharField(widget=forms.HiddenInput(), required=False)
class Meta:
model = SearchPreference
- fields = (
- 'search', 'lookup', 'unaccent', 'icontains', 'istartswith', 'trigram', 'fulltext', 'trigram_threshold')
+ fields = ('search', 'lookup', 'unaccent', 'icontains', 'istartswith', 'trigram', 'fulltext', 'trigram_threshold')
help_texts = {
- 'search': _(
- 'Select type method of search. Click here for full description of choices.'),
- 'lookup': _('Use fuzzy matching on units, keywords and ingredients when editing and importing recipes.'),
- 'unaccent': _(
- 'Fields to search ignoring accents. Selecting this option can improve or degrade search quality depending on language'),
- 'icontains': _(
- "Fields to search for partial matches. (e.g. searching for 'Pie' will return 'pie' and 'piece' and 'soapie')"),
- 'istartswith': _(
- "Fields to search for beginning of word matches. (e.g. searching for 'sa' will return 'salad' and 'sandwich')"),
- 'trigram': _(
- "Fields to 'fuzzy' search. (e.g. searching for 'recpie' will find 'recipe'.) Note: this option will conflict with 'web' and 'raw' methods of search."),
- 'fulltext': _(
- "Fields to full text search. Note: 'web', 'phrase', and 'raw' search methods only function with fulltext fields."),
+ 'search': _('Select type method of search. Click here for full description of choices.'), 'lookup':
+ _('Use fuzzy matching on units, keywords and ingredients when editing and importing recipes.'), 'unaccent':
+ _('Fields to search ignoring accents. Selecting this option can improve or degrade search quality depending on language'), 'icontains':
+ _("Fields to search for partial matches. (e.g. searching for 'Pie' will return 'pie' and 'piece' and 'soapie')"), 'istartswith':
+ _("Fields to search for beginning of word matches. (e.g. searching for 'sa' will return 'salad' and 'sandwich')"), 'trigram':
+ _("Fields to 'fuzzy' search. (e.g. searching for 'recpie' will find 'recipe'.) Note: this option will conflict with 'web' and 'raw' methods of search."), 'fulltext':
+ _("Fields to full text search. Note: 'web', 'phrase', and 'raw' search methods only function with fulltext fields."),
}
labels = {
- 'search': _('Search Method'),
- 'lookup': _('Fuzzy Lookups'),
- 'unaccent': _('Ignore Accent'),
- 'icontains': _("Partial Match"),
- 'istartswith': _("Starts With"),
- 'trigram': _("Fuzzy Search"),
- 'fulltext': _("Full Text")
+ 'search': _('Search Method'), 'lookup': _('Fuzzy Lookups'), 'unaccent': _('Ignore Accent'), 'icontains': _("Partial Match"), 'istartswith': _("Starts With"),
+ 'trigram': _("Fuzzy Search"), 'fulltext': _("Full Text")
}
widgets = {
- 'search': SelectWidget,
- 'unaccent': MultiSelectWidget,
- 'icontains': MultiSelectWidget,
- 'istartswith': MultiSelectWidget,
- 'trigram': MultiSelectWidget,
- 'fulltext': MultiSelectWidget,
+ 'search': SelectWidget, 'unaccent': MultiSelectWidget, 'icontains': MultiSelectWidget, 'istartswith': MultiSelectWidget, 'trigram': MultiSelectWidget, 'fulltext':
+ MultiSelectWidget,
}
-class ShoppingPreferenceForm(forms.ModelForm):
- prefix = 'shopping'
+# class ShoppingPreferenceForm(forms.ModelForm):
+# prefix = 'shopping'
- class Meta:
- model = UserPreference
+# class Meta:
+# model = UserPreference
- fields = (
- 'shopping_share', 'shopping_auto_sync', 'mealplan_autoadd_shopping', 'mealplan_autoexclude_onhand',
- 'mealplan_autoinclude_related', 'shopping_add_onhand', 'default_delay', 'filter_to_supermarket', 'shopping_recent_days', 'csv_delim', 'csv_prefix'
- )
+# fields = (
+# 'shopping_share', 'shopping_auto_sync', 'mealplan_autoadd_shopping', 'mealplan_autoexclude_onhand',
+# 'mealplan_autoinclude_related', 'shopping_add_onhand', 'default_delay', 'filter_to_supermarket', 'shopping_recent_days', 'csv_delim', 'csv_prefix'
+# )
- help_texts = {
- 'shopping_share': _('Users will see all items you add to your shopping list. They must add you to see items on their list.'),
- 'shopping_auto_sync': _(
- 'Setting to 0 will disable auto sync. When viewing a shopping list the list is updated every set seconds to sync changes someone else might have made. Useful when shopping with multiple people but might use a little bit '
- 'of mobile data. If lower than instance limit it is reset when saving.'
- ),
- 'mealplan_autoadd_shopping': _('Automatically add meal plan ingredients to shopping list.'),
- 'mealplan_autoinclude_related': _('When adding a meal plan to the shopping list (manually or automatically), include all related recipes.'),
- 'mealplan_autoexclude_onhand': _('When adding a meal plan to the shopping list (manually or automatically), exclude ingredients that are on hand.'),
- 'default_delay': _('Default number of hours to delay a shopping list entry.'),
- 'filter_to_supermarket': _('Filter shopping list to only include supermarket categories.'),
- 'shopping_recent_days': _('Days of recent shopping list entries to display.'),
- 'shopping_add_onhand': _("Mark food 'On Hand' when checked off shopping list."),
- 'csv_delim': _('Delimiter to use for CSV exports.'),
- 'csv_prefix': _('Prefix to add when copying list to the clipboard.'),
+# help_texts = {
+# 'shopping_share': _('Users will see all items you add to your shopping list. They must add you to see items on their list.'),
+# 'shopping_auto_sync': _(
+# 'Setting to 0 will disable auto sync. When viewing a shopping list the list is updated every set seconds to sync changes someone else might have made. Useful when shopping with multiple people but might use a little bit '
+# 'of mobile data. If lower than instance limit it is reset when saving.'
+# ),
+# 'mealplan_autoadd_shopping': _('Automatically add meal plan ingredients to shopping list.'),
+# 'mealplan_autoinclude_related': _('When adding a meal plan to the shopping list (manually or automatically), include all related recipes.'),
+# 'mealplan_autoexclude_onhand': _('When adding a meal plan to the shopping list (manually or automatically), exclude ingredients that are on hand.'),
+# 'default_delay': _('Default number of hours to delay a shopping list entry.'),
+# 'filter_to_supermarket': _('Filter shopping list to only include supermarket categories.'),
+# 'shopping_recent_days': _('Days of recent shopping list entries to display.'),
+# 'shopping_add_onhand': _("Mark food 'On Hand' when checked off shopping list."),
+# 'csv_delim': _('Delimiter to use for CSV exports.'),
+# 'csv_prefix': _('Prefix to add when copying list to the clipboard.'),
- }
- labels = {
- 'shopping_share': _('Share Shopping List'),
- 'shopping_auto_sync': _('Autosync'),
- 'mealplan_autoadd_shopping': _('Auto Add Meal Plan'),
- 'mealplan_autoexclude_onhand': _('Exclude On Hand'),
- 'mealplan_autoinclude_related': _('Include Related'),
- 'default_delay': _('Default Delay Hours'),
- 'filter_to_supermarket': _('Filter to Supermarket'),
- 'shopping_recent_days': _('Recent Days'),
- 'csv_delim': _('CSV Delimiter'),
- "csv_prefix_label": _("List Prefix"),
- 'shopping_add_onhand': _("Auto On Hand"),
- }
+# }
+# labels = {
+# 'shopping_share': _('Share Shopping List'),
+# 'shopping_auto_sync': _('Autosync'),
+# 'mealplan_autoadd_shopping': _('Auto Add Meal Plan'),
+# 'mealplan_autoexclude_onhand': _('Exclude On Hand'),
+# 'mealplan_autoinclude_related': _('Include Related'),
+# 'default_delay': _('Default Delay Hours'),
+# 'filter_to_supermarket': _('Filter to Supermarket'),
+# 'shopping_recent_days': _('Recent Days'),
+# 'csv_delim': _('CSV Delimiter'),
+# "csv_prefix_label": _("List Prefix"),
+# 'shopping_add_onhand': _("Auto On Hand"),
+# }
- widgets = {
- 'shopping_share': MultiSelectWidget
- }
+# widgets = {
+# 'shopping_share': MultiSelectWidget
+# }
+# class SpacePreferenceForm(forms.ModelForm):
+# prefix = 'space'
+# reset_food_inherit = forms.BooleanField(label=_("Reset Food Inheritance"), initial=False, required=False,
+# help_text=_("Reset all food to inherit the fields configured."))
-class SpacePreferenceForm(forms.ModelForm):
- prefix = 'space'
- reset_food_inherit = forms.BooleanField(label=_("Reset Food Inheritance"), initial=False, required=False,
- help_text=_("Reset all food to inherit the fields configured."))
+# def __init__(self, *args, **kwargs):
+# super().__init__(*args, **kwargs) # populates the post
+# self.fields['food_inherit'].queryset = Food.inheritable_fields
- def __init__(self, *args, **kwargs):
- super().__init__(*args, **kwargs) # populates the post
- self.fields['food_inherit'].queryset = Food.inheritable_fields
+# class Meta:
+# model = Space
- class Meta:
- model = Space
+# fields = ('food_inherit', 'reset_food_inherit',)
- fields = ('food_inherit', 'reset_food_inherit',)
+# help_texts = {
+# 'food_inherit': _('Fields on food that should be inherited by default.'),
+# 'use_plural': _('Use the plural form for units and food inside this space.'),
+# }
- help_texts = {
- 'food_inherit': _('Fields on food that should be inherited by default.'),
- 'use_plural': _('Use the plural form for units and food inside this space.'),
- }
-
- widgets = {
- 'food_inherit': MultiSelectWidget
- }
+# widgets = {
+# 'food_inherit': MultiSelectWidget
+# }
diff --git a/cookbook/views/edit.py b/cookbook/views/edit.py
index 356191ec..bcd874d8 100644
--- a/cookbook/views/edit.py
+++ b/cookbook/views/edit.py
@@ -10,8 +10,7 @@ from django.views.generic import UpdateView
from django.views.generic.edit import FormMixin
from cookbook.forms import CommentForm, ExternalRecipeForm, StorageForm, SyncForm, ConnectorConfigForm
-from cookbook.helper.permission_helper import (GroupRequiredMixin, OwnerRequiredMixin,
- above_space_limit, group_required)
+from cookbook.helper.permission_helper import GroupRequiredMixin, OwnerRequiredMixin, above_space_limit, group_required
from cookbook.models import Comment, Recipe, RecipeImport, Storage, Sync, ConnectorConfig
from cookbook.provider.dropbox import Dropbox
from cookbook.provider.local import Local
@@ -106,26 +105,16 @@ def edit_storage(request, pk):
instance.save()
- messages.add_message(
- request, messages.SUCCESS, _('Storage saved!')
- )
+ messages.add_message(request, messages.SUCCESS, _('Storage saved!'))
else:
- messages.add_message(
- request,
- messages.ERROR,
- _('There was an error updating this storage backend!')
- )
+ messages.add_message(request, messages.ERROR, _('There was an error updating this storage backend!'))
else:
pseudo_instance = instance
pseudo_instance.password = VALUE_NOT_CHANGED
pseudo_instance.token = VALUE_NOT_CHANGED
form = StorageForm(instance=pseudo_instance)
- return render(
- request,
- 'generic/edit_template.html',
- {'form': form, 'title': _('Storage')}
- )
+ return render(request, 'generic/edit_template.html', {'form': form, 'title': _('Storage')})
class ConnectorConfigUpdate(GroupRequiredMixin, UpdateView):
@@ -165,9 +154,7 @@ class CommentUpdate(OwnerRequiredMixin, UpdateView):
def get_context_data(self, **kwargs):
context = super(CommentUpdate, self).get_context_data(**kwargs)
context['title'] = _("Comment")
- context['view_url'] = reverse(
- 'view_recipe', args=[self.object.recipe.pk]
- )
+ context['view_url'] = reverse('view_recipe', args=[self.object.recipe.pk])
return context
@@ -206,11 +193,7 @@ class ExternalRecipeUpdate(GroupRequiredMixin, UpdateView, SpaceFormMixing):
if self.object.storage.method == Storage.LOCAL:
Local.rename_file(old_recipe, self.object.name)
- self.object.file_path = "%s/%s%s" % (
- os.path.dirname(self.object.file_path),
- self.object.name,
- os.path.splitext(self.object.file_path)[1]
- )
+ self.object.file_path = "%s/%s%s" % (os.path.dirname(self.object.file_path), self.object.name, os.path.splitext(self.object.file_path)[1])
messages.add_message(self.request, messages.SUCCESS, _('Changes saved!'))
return super(ExternalRecipeUpdate, self).form_valid(form)
@@ -227,7 +210,5 @@ class ExternalRecipeUpdate(GroupRequiredMixin, UpdateView, SpaceFormMixing):
context['title'] = _("Recipe")
context['view_url'] = reverse('view_recipe', args=[self.object.pk])
if self.object.storage:
- context['delete_external_url'] = reverse(
- 'delete_recipe_source', args=[self.object.pk]
- )
+ context['delete_external_url'] = reverse('delete_recipe_source', args=[self.object.pk])
return context
diff --git a/cookbook/views/views.py b/cookbook/views/views.py
index 6454cf0d..55474494 100644
--- a/cookbook/views/views.py
+++ b/cookbook/views/views.py
@@ -1,10 +1,10 @@
import json
import os
import re
+import subprocess
from datetime import datetime
from io import StringIO
from uuid import UUID
-import subprocess
from django.apps import apps
from django.conf import settings
@@ -23,17 +23,14 @@ from django.utils import timezone
from django.utils.translation import gettext as _
from django_scopes import scopes_disabled
-from cookbook.forms import (CommentForm, Recipe, SearchPreferenceForm, SpaceCreateForm,
- SpaceJoinForm, User, UserCreateForm, UserPreference)
+from cookbook.forms import CommentForm, Recipe, SearchPreferenceForm, SpaceCreateForm, SpaceJoinForm, User, UserCreateForm, UserPreference
from cookbook.helper.HelperFunctions import str2bool
-from cookbook.helper.permission_helper import (group_required, has_group_permission,
- share_link_valid, switch_user_active_space)
-from cookbook.models import (Comment, CookLog, InviteLink, SearchFields, SearchPreference,
- ShareLink, Space, UserSpace, ViewLog)
+from cookbook.helper.permission_helper import group_required, has_group_permission, share_link_valid, switch_user_active_space
+from cookbook.models import Comment, CookLog, InviteLink, SearchFields, SearchPreference, ShareLink, Space, UserSpace, ViewLog
from cookbook.tables import CookLogTable, ViewLogTable
from cookbook.templatetags.theming_tags import get_theming_values
from cookbook.version_info import VERSION_INFO
-from recipes.settings import PLUGINS, BASE_DIR
+from recipes.settings import BASE_DIR, PLUGINS
def index(request):
@@ -44,11 +41,7 @@ def index(request):
return HttpResponseRedirect(reverse_lazy('view_search'))
try:
- page_map = {
- UserPreference.SEARCH: reverse_lazy('view_search'),
- UserPreference.PLAN: reverse_lazy('view_plan'),
- UserPreference.BOOKS: reverse_lazy('view_books'),
- }
+ page_map = {UserPreference.SEARCH: reverse_lazy('view_search'), UserPreference.PLAN: reverse_lazy('view_plan'), UserPreference.BOOKS: reverse_lazy('view_books'), }
return HttpResponseRedirect(page_map.get(request.user.userpreference.default_page))
except UserPreference.DoesNotExist:
@@ -57,7 +50,7 @@ def index(request):
# TODO need to deprecate
def search(request):
- if has_group_permission(request.user, ('guest',)):
+ if has_group_permission(request.user, ('guest', )):
return render(request, 'search.html', {})
else:
if request.user.is_authenticated:
@@ -84,14 +77,13 @@ def space_overview(request):
_('You have the reached the maximum amount of spaces that can be owned by you.') + f' ({request.user.userpreference.max_owned_spaces})')
return HttpResponseRedirect(reverse('view_space_overview'))
- created_space = Space.objects.create(
- name=create_form.cleaned_data['name'],
- created_by=request.user,
- max_file_storage_mb=settings.SPACE_DEFAULT_MAX_FILES,
- max_recipes=settings.SPACE_DEFAULT_MAX_RECIPES,
- max_users=settings.SPACE_DEFAULT_MAX_USERS,
- allow_sharing=settings.SPACE_DEFAULT_ALLOW_SHARING,
- )
+ created_space = Space.objects.create(name=create_form.cleaned_data['name'],
+ created_by=request.user,
+ max_file_storage_mb=settings.SPACE_DEFAULT_MAX_FILES,
+ max_recipes=settings.SPACE_DEFAULT_MAX_RECIPES,
+ max_users=settings.SPACE_DEFAULT_MAX_USERS,
+ allow_sharing=settings.SPACE_DEFAULT_ALLOW_SHARING,
+ )
user_space = UserSpace.objects.create(space=created_space, user=request.user, active=False)
user_space.groups.add(Group.objects.filter(name='admin').get())
@@ -135,23 +127,18 @@ def recipe_view(request, pk, share=None):
recipe = get_object_or_404(Recipe, pk=pk)
if not request.user.is_authenticated and not share_link_valid(recipe, share):
- messages.add_message(request, messages.ERROR,
- _('You do not have the required permissions to view this page!'))
+ messages.add_message(request, messages.ERROR, _('You do not have the required permissions to view this page!'))
return HttpResponseRedirect(reverse('account_login') + '?next=' + request.path)
- if not (has_group_permission(request.user,
- ('guest',)) and recipe.space == request.space) and not share_link_valid(recipe,
- share):
- messages.add_message(request, messages.ERROR,
- _('You do not have the required permissions to view this page!'))
+ if not (has_group_permission(request.user, ('guest', )) and recipe.space == request.space) and not share_link_valid(recipe, share):
+ messages.add_message(request, messages.ERROR, _('You do not have the required permissions to view this page!'))
return HttpResponseRedirect(reverse('index'))
comments = Comment.objects.filter(recipe__space=request.space, recipe=recipe)
if request.method == "POST":
if not request.user.is_authenticated:
- messages.add_message(request, messages.ERROR,
- _('You do not have the required permissions to perform this action!'))
+ messages.add_message(request, messages.ERROR, _('You do not have the required permissions to perform this action!'))
return HttpResponseRedirect(reverse('view_recipe', kwargs={'pk': recipe.pk, 'share': share}))
comment_form = CommentForm(request.POST, prefix='comment')
@@ -167,16 +154,16 @@ def recipe_view(request, pk, share=None):
comment_form = CommentForm()
if request.user.is_authenticated:
- if not ViewLog.objects.filter(recipe=recipe, created_by=request.user,
- created_at__gt=(timezone.now() - timezone.timedelta(minutes=5)),
- space=request.space).exists():
+ if not ViewLog.objects.filter(recipe=recipe, created_by=request.user, created_at__gt=(timezone.now() - timezone.timedelta(minutes=5)), space=request.space).exists():
ViewLog.objects.create(recipe=recipe, created_by=request.user, space=request.space)
+
if request.method == "GET":
servings = request.GET.get("servings")
return render(request, 'recipe_view.html',
{'recipe': recipe, 'comments': comments, 'comment_form': comment_form, 'share': share, 'servings': servings })
+
@group_required('user')
def books(request):
return render(request, 'books.html', {})
@@ -239,12 +226,8 @@ def shopping_settings(request):
if search_form.is_valid():
if not sp:
sp = SearchPreferenceForm(user=request.user)
- fields_searched = (
- len(search_form.cleaned_data['icontains'])
- + len(search_form.cleaned_data['istartswith'])
- + len(search_form.cleaned_data['trigram'])
- + len(search_form.cleaned_data['fulltext'])
- )
+ fields_searched = (len(search_form.cleaned_data['icontains']) + len(search_form.cleaned_data['istartswith']) + len(search_form.cleaned_data['trigram'])
+ + len(search_form.cleaned_data['fulltext']))
if search_form.cleaned_data['preset'] == 'fuzzy':
sp.search = SearchPreference.SIMPLE
sp.lookup = True
@@ -269,13 +252,10 @@ def shopping_settings(request):
elif fields_searched == 0:
search_form.add_error(None, _('You must select at least one field to search!'))
search_error = True
- elif search_form.cleaned_data['search'] in ['websearch', 'raw'] and len(
- search_form.cleaned_data['fulltext']) == 0:
- search_form.add_error('search',
- _('To use this search method you must select at least one full text search field!'))
+ elif search_form.cleaned_data['search'] in ['websearch', 'raw'] and len(search_form.cleaned_data['fulltext']) == 0:
+ search_form.add_error('search', _('To use this search method you must select at least one full text search field!'))
search_error = True
- elif search_form.cleaned_data['search'] in ['websearch', 'raw'] and len(
- search_form.cleaned_data['trigram']) > 0:
+ elif search_form.cleaned_data['search'] in ['websearch', 'raw'] and len(search_form.cleaned_data['trigram']) > 0:
search_form.add_error(None, _('Fuzzy search is not compatible with this search method!'))
search_error = True
else:
@@ -291,8 +271,7 @@ def shopping_settings(request):
else:
search_error = True
- fields_searched = len(sp.icontains.all()) + len(sp.istartswith.all()) + len(sp.trigram.all()) + len(
- sp.fulltext.all())
+ fields_searched = len(sp.icontains.all()) + len(sp.istartswith.all()) + len(sp.trigram.all()) + len(sp.fulltext.all())
if sp and not search_error and fields_searched > 0:
search_form = SearchPreferenceForm(instance=sp)
elif not search_error:
@@ -305,23 +284,13 @@ def shopping_settings(request):
sp.fulltext.clear()
sp.save()
- return render(request, 'settings.html', {
- 'search_form': search_form,
- })
+ return render(request, 'settings.html', {'search_form': search_form, })
@group_required('guest')
def history(request):
- view_log = ViewLogTable(
- ViewLog.objects.filter(
- created_by=request.user, space=request.space
- ).order_by('-created_at').all()
- )
- cook_log = CookLogTable(
- CookLog.objects.filter(
- created_by=request.user
- ).order_by('-created_at').all()
- )
+ view_log = ViewLogTable(ViewLog.objects.filter(created_by=request.user, space=request.space).order_by('-created_at').all())
+ cook_log = CookLogTable(CookLog.objects.filter(created_by=request.user).order_by('-created_at').all())
return render(request, 'history.html', {'view_log': view_log, 'cook_log': cook_log})
@@ -344,12 +313,10 @@ def system(request):
database_message = _('Everything is fine!')
elif postgres_ver < postgres_current - 2:
database_status = 'danger'
- database_message = _('PostgreSQL %(v)s is deprecated. Upgrade to a fully supported version!') % {
- 'v': postgres_ver}
+ database_message = _('PostgreSQL %(v)s is deprecated. Upgrade to a fully supported version!') % {'v': postgres_ver}
else:
database_status = 'info'
- database_message = _('You are running PostgreSQL %(v1)s. PostgreSQL %(v2)s is recommended') % {
- 'v1': postgres_ver, 'v2': postgres_current}
+ database_message = _('You are running PostgreSQL %(v1)s. PostgreSQL %(v2)s is recommended') % {'v1': postgres_ver, 'v2': postgres_current}
else:
database_status = 'info'
database_message = _(
@@ -378,34 +345,26 @@ def system(request):
pass
else:
current_app = row
- migration_info[current_app] = {'app': current_app, 'unapplied_migrations': [], 'applied_migrations': [],
- 'total': 0}
+ migration_info[current_app] = {'app': current_app, 'unapplied_migrations': [], 'applied_migrations': [], 'total': 0}
for key in migration_info.keys():
- migration_info[key]['total'] = len(migration_info[key]['unapplied_migrations']) + len(
- migration_info[key]['applied_migrations'])
+ migration_info[key]['total'] = len(migration_info[key]['unapplied_migrations']) + len(migration_info[key]['applied_migrations'])
- return render(request, 'system.html', {
- 'gunicorn_media': settings.GUNICORN_MEDIA,
- 'debug': settings.DEBUG,
- 'postgres': postgres,
- 'postgres_version': postgres_ver,
- 'postgres_status': database_status,
- 'postgres_message': database_message,
- 'version_info': VERSION_INFO,
- 'plugins': PLUGINS,
- 'secret_key': secret_key,
- 'orphans': orphans,
- 'migration_info': migration_info,
- 'missing_migration': missing_migration,
- })
+ return render(
+ request, 'system.html', {
+ 'gunicorn_media': settings.GUNICORN_MEDIA, 'debug': settings.DEBUG, 'postgres': postgres, 'postgres_version': postgres_ver, 'postgres_status': database_status,
+ 'postgres_message': database_message, 'version_info': VERSION_INFO, 'plugins': PLUGINS, 'secret_key': secret_key, 'orphans': orphans, 'migration_info': migration_info,
+ 'missing_migration': missing_migration,
+ })
def setup(request):
with scopes_disabled():
if User.objects.count() > 0 or 'django.contrib.auth.backends.RemoteUserBackend' in settings.AUTHENTICATION_BACKENDS:
- messages.add_message(request, messages.ERROR,
- _('The setup page can only be used to create the first user! If you have forgotten your superuser credentials please consult the django documentation on how to reset passwords.'))
+ messages.add_message(
+ request, messages.ERROR,
+ _('The setup page can only be used to create the first user! If you have forgotten your superuser credentials please consult the django documentation on how to reset passwords.'
+ ))
return HttpResponseRedirect(reverse('account_login'))
if request.method == 'POST':
@@ -445,8 +404,7 @@ def invite_link(request, token):
link.used_by = request.user
link.save()
- user_space = UserSpace.objects.create(user=request.user, space=link.space,
- internal_note=link.internal_note, invite_link=link, active=False)
+ user_space = UserSpace.objects.create(user=request.user, space=link.space, internal_note=link.internal_note, invite_link=link, active=False)
if request.user.userspace_set.count() == 1:
user_space.active = True
@@ -476,66 +434,36 @@ def space_manage(request, space_id):
def report_share_abuse(request, token):
if not settings.SHARING_ABUSE:
- messages.add_message(request, messages.WARNING,
- _('Reporting share links is not enabled for this instance. Please notify the page administrator to report problems.'))
+ messages.add_message(request, messages.WARNING, _('Reporting share links is not enabled for this instance. Please notify the page administrator to report problems.'))
else:
if link := ShareLink.objects.filter(uuid=token).first():
link.abuse_blocked = True
link.save()
- messages.add_message(request, messages.WARNING,
- _('Recipe sharing link has been disabled! For additional information please contact the page administrator.'))
+ messages.add_message(request, messages.WARNING, _('Recipe sharing link has been disabled! For additional information please contact the page administrator.'))
return HttpResponseRedirect(reverse('index'))
def web_manifest(request):
theme_values = get_theming_values(request)
- icons = [
- {"src": theme_values['logo_color_svg'], "sizes": "any"},
- {"src": theme_values['logo_color_144'], "type": "image/png", "sizes": "144x144"},
- {"src": theme_values['logo_color_512'], "type": "image/png", "sizes": "512x512"}
- ]
+ icons = [{"src": theme_values['logo_color_svg'], "sizes": "any"}, {"src": theme_values['logo_color_144'], "type": "image/png", "sizes": "144x144"},
+ {"src": theme_values['logo_color_512'], "type": "image/png", "sizes": "512x512"}]
manifest_info = {
- "name": theme_values['app_name'],
- "short_name": theme_values['app_name'],
- "description": _("Manage recipes, shopping list, meal plans and more."),
- "icons": icons,
- "start_url": "./search",
- "background_color": theme_values['nav_bg_color'],
- "display": "standalone",
- "scope": ".",
- "theme_color": theme_values['nav_bg_color'],
- "shortcuts": [
- {
- "name": _("Plan"),
- "short_name": _("Plan"),
- "description": _("View your meal Plan"),
- "url": "./plan"
- },
- {
- "name": _("Books"),
- "short_name": _("Books"),
- "description": _("View your cookbooks"),
- "url": "./books"
- },
- {
- "name": _("Shopping"),
- "short_name": _("Shopping"),
- "description": _("View your shopping lists"),
- "url": "./list/shopping-list/"
- }
- ],
- "share_target": {
- "action": "/data/import/url",
- "method": "GET",
- "params": {
- "title": "title",
- "url": "url",
- "text": "text"
-
- }
- }
+ "name":
+ theme_values['app_name'], "short_name":
+ theme_values['app_name'], "description":
+ _("Manage recipes, shopping list, meal plans and more."), "icons":
+ icons, "start_url":
+ "./search", "background_color":
+ theme_values['nav_bg_color'], "display":
+ "standalone", "scope":
+ ".", "theme_color":
+ theme_values['nav_bg_color'], "shortcuts":
+ [{"name": _("Plan"), "short_name": _("Plan"), "description": _("View your meal Plan"), "url":
+ "./plan"}, {"name": _("Books"), "short_name": _("Books"), "description": _("View your cookbooks"), "url": "./books"},
+ {"name": _("Shopping"), "short_name": _("Shopping"), "description": _("View your shopping lists"), "url":
+ "./list/shopping-list/"}], "share_target": {"action": "/data/import/url", "method": "GET", "params": {"title": "title", "url": "url", "text": "text"}}
}
return JsonResponse(manifest_info, json_dumps_params={'indent': 4})
@@ -565,9 +493,7 @@ def test(request):
from cookbook.helper.ingredient_parser import IngredientParser
parser = IngredientParser(request, False)
- data = {
- 'original': '90g golden syrup'
- }
+ data = {'original': '90g golden syrup'}
data['parsed'] = parser.parse(data['original'])
return render(request, 'test.html', {'data': data})