refactor generic url creation

This commit is contained in:
vabene1111 2020-03-17 17:23:39 +01:00
parent 09ff7e82f1
commit 17b9519fa9
12 changed files with 53 additions and 52 deletions

View File

@ -1,8 +1,14 @@
import re
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
from django.db import models 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): class UserPreference(models.Model):
# Themes # Themes
BOOTSTRAP = 'BOOTSTRAP' BOOTSTRAP = 'BOOTSTRAP'

View File

@ -111,9 +111,9 @@
class="fas fa-database"></i> {% trans 'Storage Backends' %}</a> class="fas fa-database"></i> {% trans 'Storage Backends' %}</a>
<a class="dropdown-item" href="{% url 'data_sync' %}"><i <a class="dropdown-item" href="{% url 'data_sync' %}"><i
class="fas fa-sync-alt"></i> {% trans 'Configure Sync' %}</a> class="fas fa-sync-alt"></i> {% trans 'Configure Sync' %}</a>
<a class="dropdown-item" href="{% url 'list_import' %}"><i <a class="dropdown-item" href="{% url 'list_recipe_import' %}"><i
class="far fa-file-alt"></i> {% trans 'Import Recipes' %}</a> class="far fa-file-alt"></i> {% trans 'Import Recipes' %}</a>
<a class="dropdown-item" href="{% url 'list_import_log' %}"><i <a class="dropdown-item" href="{% url 'list_sync_log' %}"><i
class="fas fa-history"></i> {% trans 'Import Log' %}</a> class="fas fa-history"></i> {% trans 'Import Log' %}</a>
<a class="dropdown-item" href="{% url 'data_stats' %}"><i <a class="dropdown-item" href="{% url 'data_stats' %}"><i
class="fas fa-chart-line"></i> {% trans 'Statistics' %}</a> class="fas fa-chart-line"></i> {% trans 'Statistics' %}</a>

View File

@ -10,7 +10,7 @@
<h2>{% trans 'Recipe Books' %}</h2> <h2>{% trans 'Recipe Books' %}</h2>
</div> </div>
<div class="col col-md-3" style="text-align: right"> <div class="col col-md-3" style="text-align: right">
<a href="{% url 'new_book' %}" class="btn btn-success"><i <a href="{% url 'new_recipe_book' %}" class="btn btn-success"><i
class="fas fa-plus-circle"></i> {% trans 'New Book' %}</a> class="fas fa-plus-circle"></i> {% trans 'New Book' %}</a>
</div> </div>
</div> </div>

View File

@ -45,7 +45,7 @@
<hr> <hr>
<button class="btn btn-success" type="submit"><i class="fas fa-save"></i> {% trans 'Save' %}</button> <button class="btn btn-success" type="submit"><i class="fas fa-save"></i> {% trans 'Save' %}</button>
<a href="{% url 'redirect_delete' form.instance|get_class|lower form.instance.pk %}" <a href="{% delete_url form.instance|get_class form.instance.pk %}"
class="btn btn-danger"><i class="fas fa-trash-alt"></i> {% trans 'Delete' %}</a> class="btn btn-danger"><i class="fas fa-trash-alt"></i> {% trans 'Delete' %}</a>
{% if view_url %} {% if view_url %}
<a href="{{ view_url }}" class="btn btn-info"><i class="far fa-eye"></i> {% trans 'View' %}</a> <a href="{{ view_url }}" class="btn btn-info"><i class="far fa-eye"></i> {% trans 'View' %}</a>

View File

@ -13,7 +13,7 @@
<h3>{% trans 'Edit' %} {{ title }}</h3> <h3>{% trans 'Edit' %} {{ title }}</h3>
{% if form.Meta.model|get_class == 'Storage' %} {% if form.Meta.model|get_class_name == 'Storage' %}
{% include 'include/storage_backend_warning.html' %} {% include 'include/storage_backend_warning.html' %}
{% endif %} {% endif %}
@ -21,7 +21,7 @@
{% csrf_token %} {% csrf_token %}
{{ form|crispy }} {{ form|crispy }}
<button class="btn btn-success" type="submit"><i class="fas fa-save"></i> {% trans 'Save' %}</button> <button class="btn btn-success" type="submit"><i class="fas fa-save"></i> {% trans 'Save' %}</button>
<a href="{% url 'redirect_delete' form.instance|get_class|lower form.instance.pk %}" <a href="{% delete_url form.instance|get_class form.instance.pk %}"
class="btn btn-danger"><i class="fas fa-trash-alt"></i> {% trans 'Delete' %}</a> class="btn btn-danger"><i class="fas fa-trash-alt"></i> {% trans 'Delete' %}</a>
{% if view_url %} {% if view_url %}
<a href="{{ view_url }}" class="btn btn-info"><i class="far fa-eye"></i> {% trans 'View' %}</a> <a href="{{ view_url }}" class="btn btn-info"><i class="far fa-eye"></i> {% trans 'View' %}</a>

View File

@ -13,7 +13,7 @@
<h3>{% trans 'New' %} {{ title }} </h3> <h3>{% trans 'New' %} {{ title }} </h3>
{% if form.Meta.model|get_class == 'Storage' %} {% if form.Meta.model|get_class_name == 'Storage' %}
{% include 'include/storage_backend_warning.html' %} {% include 'include/storage_backend_warning.html' %}
{% endif %} {% endif %}

View File

@ -10,7 +10,7 @@
{% block content %} {% block content %}
<h3> <h3>
{% trans 'Meal-Plan' %} <a href="{% url 'new_plan' %}"><i class="fas fa-plus-circle"></i></a> {% trans 'Meal-Plan' %} <a href="{% url 'new_meal_plan' %}"><i class="fas fa-plus-circle"></i></a>
</h3> </h3>
<div class="row"> <div class="row">
@ -55,7 +55,7 @@
{% for day_key, days_value in plan_value.days.items %} {% for day_key, days_value in plan_value.days.items %}
<td> <td>
{% for mp in days_value %} {% for mp in days_value %}
<a href="{% url 'edit_plan' mp.pk %}"><i class="fas fa-edit"></i></a> <a href="{% url 'edit_meal_plan' mp.pk %}"><i class="fas fa-edit"></i></a>
<a href="{% url 'view_recipe' mp.recipe.id %}">{{ mp.recipe.name }}</a><br/> <a href="{% url 'view_recipe' mp.recipe.id %}">{{ mp.recipe.name }}</a><br/>
{% endfor %} {% endfor %}
</td> </td>

View File

@ -58,7 +58,7 @@
<a class="btn btn-warning" href="{% url 'view_shopping' %}?r={{ recipe.pk }}"><i <a class="btn btn-warning" href="{% url 'view_shopping' %}?r={{ recipe.pk }}"><i
class="fas fa-shopping-cart"></i></a> class="fas fa-shopping-cart"></i></a>
{% endif %} {% endif %}
<a class="btn btn-info" href="{% url 'new_plan' %}?recipe={{ recipe.pk }}"><i <a class="btn btn-info" href="{% url 'new_meal_plan' %}?recipe={{ recipe.pk }}"><i
class="fas fa-calendar"></i></a> class="fas fa-calendar"></i></a>
</div> </div>
</div> </div>

View File

@ -2,17 +2,29 @@ from django import template
import markdown as md import markdown as md
import bleach import bleach
from bleach_whitelist import markdown_tags, markdown_attrs, all_styles, print_attrs 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.helper.mdx_attributes import MarkdownFormatExtension
from cookbook.models import get_model_name
register = template.Library() register = template.Library()
@register.filter(name='get_class') @register.filter()
def get_class(value): def get_class_name(value):
return value.__class__.__name__ 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() @register.filter()
def markdown(value): def markdown(value):
tags = markdown_tags + ['pre', 'table', 'td', 'tr', 'th', 'tbody', 'style', 'thead'] tags = markdown_tags + ['pre', 'table', 'td', 'tr', 'th', 'tbody', 'style', 'thead']

View File

@ -1,3 +1,5 @@
from pydoc import locate
from django.urls import path from django.urls import path
from .views import * from .views import *
@ -13,46 +15,16 @@ urlpatterns = [
path('view/recipe/<int:pk>', views.recipe_view, name='view_recipe'), path('view/recipe/<int:pk>', views.recipe_view, name='view_recipe'),
path('new/recipe/', new.RecipeCreate.as_view(), name='new_recipe'),
path('new/recipe_import/<int:import_id>/', 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/<int:pk>/', edit.switch_recipe, name='edit_recipe'),
path('edit/recipe/internal/<int:pk>/', edit.internal_recipe_update, name='edit_internal_recipe'), path('edit/recipe/internal/<int:pk>/', edit.internal_recipe_update, name='edit_internal_recipe'),
# for internal use only # for internal use only
path('edit/recipe/external/<int:pk>/', edit.RecipeUpdate.as_view(), name='edit_external_recipe'), path('edit/recipe/external/<int:pk>/', edit.RecipeUpdate.as_view(), name='edit_external_recipe'),
# for internal use only # for internal use only
path('edit/recipe/convert/<int:pk>/', edit.convert_recipe, name='edit_convert_recipe'), # for internal use only path('edit/recipe/convert/<int:pk>/', edit.convert_recipe, name='edit_convert_recipe'), # for internal use only
path('edit/keyword/<int:pk>/', edit.KeywordUpdate.as_view(), name='edit_keyword'),
path('edit/sync/<int:pk>/', edit.SyncUpdate.as_view(), name='edit_sync'),
path('edit/import/<int:pk>/', edit.ImportUpdate.as_view(), name='edit_import'),
path('edit/storage/<int:pk>/', edit.edit_storage, name='edit_storage'), path('edit/storage/<int:pk>/', edit.edit_storage, name='edit_storage'),
path('edit/comment/<int:pk>/', edit.CommentUpdate.as_view(), name='edit_comment'),
path('edit/recipe-book/<int:pk>/', edit.RecipeBookUpdate.as_view(), name='edit_recipe_book'),
path('edit/plan/<int:pk>/', edit.MealPlanUpdate.as_view(), name='edit_plan'),
path('edit/ingredient/', edit.edit_ingredients, name='edit_ingredient'), path('edit/ingredient/', edit.edit_ingredients, name='edit_ingredient'),
path('redirect/delete/<slug:name>/<int:pk>/', delete.delete_redirect, name='redirect_delete'),
path('delete/recipe/<int:pk>/', delete.RecipeDelete.as_view(), name='delete_recipe'),
path('delete/recipe-source/<int:pk>/', delete.RecipeSourceDelete.as_view(), name='delete_recipe_source'), path('delete/recipe-source/<int:pk>/', delete.RecipeSourceDelete.as_view(), name='delete_recipe_source'),
path('delete/keyword/<int:pk>/', delete.KeywordDelete.as_view(), name='delete_keyword'),
path('delete/sync/<int:pk>/', delete.MonitorDelete.as_view(), name='delete_sync'),
path('delete/import/<int:pk>/', delete.ImportDelete.as_view(), name='delete_import'),
path('delete/storage/<int:pk>/', delete.StorageDelete.as_view(), name='delete_storage'),
path('delete/comment/<int:pk>/', delete.CommentDelete.as_view(), name='delete_comment'),
path('delete/recipe-book/<int:pk>/', delete.RecipeBookDelete.as_view(), name='delete_recipe_book'),
path('delete/recipe-book-entry/<int:pk>/', delete.RecipeBookEntryDelete.as_view(), name='delete_recipe_book_entry'),
path('delete/plan/<int:pk>/', delete.MealPlanDelete.as_view(), name='delete_plan'),
path('data/sync', data.sync, name='data_sync'), # TODO move to generic "new" view 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'), 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/ingredient/', dal.IngredientsAutocomplete.as_view(), name='dal_ingredient'),
path('dal/unit/', dal.UnitAutocomplete.as_view(), name='dal_unit'), 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}/<int:pk>/', 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}/<int:pk>/', c.as_view(), name=f'delete_{py_name}'))

View File

@ -1,5 +1,4 @@
from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import LoginRequiredMixin
from django.shortcuts import redirect
from django.urls import reverse_lazy from django.urls import reverse_lazy
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
from django.views.generic import DeleteView from django.views.generic import DeleteView
@ -10,11 +9,6 @@ from cookbook.provider.dropbox import Dropbox
from cookbook.provider.nextcloud import Nextcloud from cookbook.provider.nextcloud import Nextcloud
# Generic Delete views
def delete_redirect(request, name, pk):
return redirect(('delete_' + name), pk)
class RecipeDelete(LoginRequiredMixin, DeleteView): class RecipeDelete(LoginRequiredMixin, DeleteView):
template_name = "generic/delete_template.html" template_name = "generic/delete_template.html"
model = Recipe model = Recipe
@ -57,13 +51,13 @@ class ImportDelete(LoginRequiredMixin, DeleteView):
return context return context
class MonitorDelete(LoginRequiredMixin, DeleteView): class SyncDelete(LoginRequiredMixin, DeleteView):
template_name = "generic/delete_template.html" template_name = "generic/delete_template.html"
model = Sync model = Sync
success_url = reverse_lazy('data_sync') success_url = reverse_lazy('data_sync')
def get_context_data(self, **kwargs): 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") context['title'] = _("Monitor")
return context return context

View File

@ -192,7 +192,7 @@ def edit_storage(request, pk):
form = StorageForm(instance=pseudo_instance) form = StorageForm(instance=pseudo_instance)
return render(request, 'generic/edit_template.html', return render(request, 'generic/edit_template.html',
{'form': form, 'view_url': reverse('view_recipe', args=[pk])}) {'form': form})
class CommentUpdate(LoginRequiredMixin, UpdateView): class CommentUpdate(LoginRequiredMixin, UpdateView):
@ -342,4 +342,3 @@ def edit_ingredients(request):
ingredients_form = IngredientMergeForm() ingredients_form = IngredientMergeForm()
return render(request, 'forms/ingredients.html', {'units_form': units_form, 'ingredients_form': ingredients_form}) return render(request, 'forms/ingredients.html', {'units_form': units_form, 'ingredients_form': ingredients_form})