diff --git a/cookbook/models.py b/cookbook/models.py
index a3111263a..d3c494cd2 100644
--- a/cookbook/models.py
+++ b/cookbook/models.py
@@ -1,8 +1,14 @@
+import re
+
from django.contrib.auth.models import User
from django.utils.translation import gettext as _
from django.db import models
+def get_model_name(model):
+ return ('_'.join(re.findall('[A-Z][^A-Z]*', model.__name__))).lower()
+
+
class UserPreference(models.Model):
# Themes
BOOTSTRAP = 'BOOTSTRAP'
diff --git a/cookbook/templates/base.html b/cookbook/templates/base.html
index a436e68dc..0837324eb 100644
--- a/cookbook/templates/base.html
+++ b/cookbook/templates/base.html
@@ -111,9 +111,9 @@
class="fas fa-database"> {% trans 'Storage Backends' %}
{% trans 'Configure Sync' %}
- {% trans 'Import Recipes' %}
- {% trans 'Import Log' %}
{% trans 'Statistics' %}
diff --git a/cookbook/templates/books.html b/cookbook/templates/books.html
index b1186c68c..32a95ebb8 100644
--- a/cookbook/templates/books.html
+++ b/cookbook/templates/books.html
@@ -10,7 +10,7 @@
{% trans 'Recipe Books' %}
diff --git a/cookbook/templates/forms/edit_internal_recipe.html b/cookbook/templates/forms/edit_internal_recipe.html
index fbb718ce9..604f28a57 100644
--- a/cookbook/templates/forms/edit_internal_recipe.html
+++ b/cookbook/templates/forms/edit_internal_recipe.html
@@ -45,7 +45,7 @@
- {% trans 'Delete' %}
{% if view_url %}
{% trans 'View' %}
diff --git a/cookbook/templates/generic/edit_template.html b/cookbook/templates/generic/edit_template.html
index 92a75a3d3..fde67fb77 100644
--- a/cookbook/templates/generic/edit_template.html
+++ b/cookbook/templates/generic/edit_template.html
@@ -13,7 +13,7 @@
{% trans 'Edit' %} {{ title }}
- {% if form.Meta.model|get_class == 'Storage' %}
+ {% if form.Meta.model|get_class_name == 'Storage' %}
{% include 'include/storage_backend_warning.html' %}
{% endif %}
@@ -21,7 +21,7 @@
{% csrf_token %}
{{ form|crispy }}
- {% trans 'Delete' %}
{% if view_url %}
{% trans 'View' %}
diff --git a/cookbook/templates/generic/new_template.html b/cookbook/templates/generic/new_template.html
index 1dc82bc2d..4f1e9fd44 100644
--- a/cookbook/templates/generic/new_template.html
+++ b/cookbook/templates/generic/new_template.html
@@ -13,7 +13,7 @@
{% trans 'New' %} {{ title }}
- {% if form.Meta.model|get_class == 'Storage' %}
+ {% if form.Meta.model|get_class_name == 'Storage' %}
{% include 'include/storage_backend_warning.html' %}
{% endif %}
diff --git a/cookbook/templates/meal_plan.html b/cookbook/templates/meal_plan.html
index 78e3ca0b0..c2956916a 100644
--- a/cookbook/templates/meal_plan.html
+++ b/cookbook/templates/meal_plan.html
@@ -10,7 +10,7 @@
{% block content %}
- {% trans 'Meal-Plan' %}
+ {% trans 'Meal-Plan' %}
@@ -55,7 +55,7 @@
{% for day_key, days_value in plan_value.days.items %}
{% for mp in days_value %}
-
+
{{ mp.recipe.name }}
{% endfor %}
|
diff --git a/cookbook/templates/recipe_view.html b/cookbook/templates/recipe_view.html
index c79df2782..6cfc12569 100644
--- a/cookbook/templates/recipe_view.html
+++ b/cookbook/templates/recipe_view.html
@@ -58,7 +58,7 @@
{% endif %}
-
diff --git a/cookbook/templatetags/custom_tags.py b/cookbook/templatetags/custom_tags.py
index d759ec409..5e8b30cd8 100644
--- a/cookbook/templatetags/custom_tags.py
+++ b/cookbook/templatetags/custom_tags.py
@@ -2,17 +2,29 @@ from django import template
import markdown as md
import bleach
from bleach_whitelist import markdown_tags, markdown_attrs, all_styles, print_attrs
+from django.urls import reverse
from cookbook.helper.mdx_attributes import MarkdownFormatExtension
+from cookbook.models import get_model_name
register = template.Library()
-@register.filter(name='get_class')
-def get_class(value):
+@register.filter()
+def get_class_name(value):
return value.__class__.__name__
+@register.filter()
+def get_class(value):
+ return value.__class__
+
+
+@register.simple_tag
+def delete_url(model, pk):
+ return reverse(f'delete_{get_model_name(model)}', args=[pk])
+
+
@register.filter()
def markdown(value):
tags = markdown_tags + ['pre', 'table', 'td', 'tr', 'th', 'tbody', 'style', 'thead']
diff --git a/cookbook/urls.py b/cookbook/urls.py
index 066ebe74a..8b9ff4d1f 100644
--- a/cookbook/urls.py
+++ b/cookbook/urls.py
@@ -1,3 +1,5 @@
+from pydoc import locate
+
from django.urls import path
from .views import *
@@ -13,46 +15,16 @@ urlpatterns = [
path('view/recipe/', views.recipe_view, name='view_recipe'),
- path('new/recipe/', new.RecipeCreate.as_view(), name='new_recipe'),
- path('new/recipe_import//', new.create_new_external_recipe, name='new_recipe_import'),
- path('new/keyword/', new.KeywordCreate.as_view(), name='new_keyword'),
- path('new/storage/', new.StorageCreate.as_view(), name='new_storage'),
- path('new/book/', new.RecipeBookCreate.as_view(), name='new_book'),
- path('new/plan/', new.MealPlanCreate.as_view(), name='new_plan'),
-
- path('list/keyword', lists.keyword, name='list_keyword'),
- path('list/import_log', lists.sync_log, name='list_import_log'),
- path('list/import', lists.recipe_import, name='list_import'),
- path('list/storage', lists.storage, name='list_storage'),
-
- path('edit/recipe//', edit.switch_recipe, name='edit_recipe'),
path('edit/recipe/internal//', edit.internal_recipe_update, name='edit_internal_recipe'),
# for internal use only
path('edit/recipe/external//', edit.RecipeUpdate.as_view(), name='edit_external_recipe'),
# for internal use only
path('edit/recipe/convert//', edit.convert_recipe, name='edit_convert_recipe'), # for internal use only
- path('edit/keyword//', edit.KeywordUpdate.as_view(), name='edit_keyword'),
- path('edit/sync//', edit.SyncUpdate.as_view(), name='edit_sync'),
- path('edit/import//', edit.ImportUpdate.as_view(), name='edit_import'),
path('edit/storage//', edit.edit_storage, name='edit_storage'),
- path('edit/comment//', edit.CommentUpdate.as_view(), name='edit_comment'),
- path('edit/recipe-book//', edit.RecipeBookUpdate.as_view(), name='edit_recipe_book'),
- path('edit/plan//', edit.MealPlanUpdate.as_view(), name='edit_plan'),
path('edit/ingredient/', edit.edit_ingredients, name='edit_ingredient'),
- path('redirect/delete///', delete.delete_redirect, name='redirect_delete'),
-
- path('delete/recipe//', delete.RecipeDelete.as_view(), name='delete_recipe'),
path('delete/recipe-source//', delete.RecipeSourceDelete.as_view(), name='delete_recipe_source'),
- path('delete/keyword//', delete.KeywordDelete.as_view(), name='delete_keyword'),
- path('delete/sync//', delete.MonitorDelete.as_view(), name='delete_sync'),
- path('delete/import//', delete.ImportDelete.as_view(), name='delete_import'),
- path('delete/storage//', delete.StorageDelete.as_view(), name='delete_storage'),
- path('delete/comment//', delete.CommentDelete.as_view(), name='delete_comment'),
- path('delete/recipe-book//', delete.RecipeBookDelete.as_view(), name='delete_recipe_book'),
- path('delete/recipe-book-entry//', delete.RecipeBookEntryDelete.as_view(), name='delete_recipe_book_entry'),
- path('delete/plan//', delete.MealPlanDelete.as_view(), name='delete_plan'),
path('data/sync', data.sync, name='data_sync'), # TODO move to generic "new" view
path('data/batch/edit', data.batch_edit, name='data_batch_edit'),
@@ -69,3 +41,21 @@ urlpatterns = [
path('dal/ingredient/', dal.IngredientsAutocomplete.as_view(), name='dal_ingredient'),
path('dal/unit/', dal.UnitAutocomplete.as_view(), name='dal_unit'),
]
+
+generic_models = (Recipe, RecipeImport, Storage, RecipeBook, MealPlan, SyncLog, Sync, Comment, RecipeBookEntry, Keyword)
+
+for m in generic_models:
+ py_name = get_model_name(m)
+ url_name = py_name.replace('_', '-')
+
+ if c := locate(f'cookbook.views.new.{m.__name__}Create'):
+ urlpatterns.append(path(f'new/{url_name}/', c.as_view(), name=f'new_{py_name}'))
+
+ if c := locate(f'cookbook.views.edit.{m.__name__}Update'):
+ urlpatterns.append(path(f'edit/{url_name}//', c.as_view(), name=f'edit_{py_name}'))
+
+ if c := getattr(lists, py_name, None):
+ urlpatterns.append(path(f'list/{url_name}/', c, name=f'list_{py_name}'))
+
+ if c := locate(f'cookbook.views.delete.{m.__name__}Delete'):
+ urlpatterns.append(path(f'delete/{url_name}//', c.as_view(), name=f'delete_{py_name}'))
diff --git a/cookbook/views/delete.py b/cookbook/views/delete.py
index da79ed212..288be2f6e 100644
--- a/cookbook/views/delete.py
+++ b/cookbook/views/delete.py
@@ -1,5 +1,4 @@
from django.contrib.auth.mixins import LoginRequiredMixin
-from django.shortcuts import redirect
from django.urls import reverse_lazy
from django.utils.translation import gettext as _
from django.views.generic import DeleteView
@@ -10,11 +9,6 @@ from cookbook.provider.dropbox import Dropbox
from cookbook.provider.nextcloud import Nextcloud
-# Generic Delete views
-def delete_redirect(request, name, pk):
- return redirect(('delete_' + name), pk)
-
-
class RecipeDelete(LoginRequiredMixin, DeleteView):
template_name = "generic/delete_template.html"
model = Recipe
@@ -57,13 +51,13 @@ class ImportDelete(LoginRequiredMixin, DeleteView):
return context
-class MonitorDelete(LoginRequiredMixin, DeleteView):
+class SyncDelete(LoginRequiredMixin, DeleteView):
template_name = "generic/delete_template.html"
model = Sync
success_url = reverse_lazy('data_sync')
def get_context_data(self, **kwargs):
- context = super(MonitorDelete, self).get_context_data(**kwargs)
+ context = super(SyncDelete, self).get_context_data(**kwargs)
context['title'] = _("Monitor")
return context
diff --git a/cookbook/views/edit.py b/cookbook/views/edit.py
index 000d079aa..cfb91541e 100644
--- a/cookbook/views/edit.py
+++ b/cookbook/views/edit.py
@@ -192,7 +192,7 @@ def edit_storage(request, pk):
form = StorageForm(instance=pseudo_instance)
return render(request, 'generic/edit_template.html',
- {'form': form, 'view_url': reverse('view_recipe', args=[pk])})
+ {'form': form})
class CommentUpdate(LoginRequiredMixin, UpdateView):
@@ -342,4 +342,3 @@ def edit_ingredients(request):
ingredients_form = IngredientMergeForm()
return render(request, 'forms/ingredients.html', {'units_form': units_form, 'ingredients_form': ingredients_form})
-