diff --git a/cookbook/filters.py b/cookbook/filters.py
index af093e3c..80662e67 100644
--- a/cookbook/filters.py
+++ b/cookbook/filters.py
@@ -44,3 +44,11 @@ class RecipeFilter(django_filters.FilterSet):
class Meta:
model = Recipe
fields = ['name', 'keywords', 'ingredients', 'internal']
+
+
+class IngredientFilter(django_filters.FilterSet):
+ name = django_filters.CharFilter(lookup_expr='icontains')
+
+ class Meta:
+ model = Ingredient
+ fields = ['name']
diff --git a/cookbook/forms.py b/cookbook/forms.py
index 126348c7..55f0c09e 100644
--- a/cookbook/forms.py
+++ b/cookbook/forms.py
@@ -141,6 +141,13 @@ class KeywordForm(forms.ModelForm):
widgets = {'icon': EmojiPickerTextInput}
+class IngredientForm(forms.ModelForm):
+ class Meta:
+ model = Ingredient
+ fields = ('name', 'recipe')
+ widgets = {'recipe': SelectWidget}
+
+
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'}),
diff --git a/cookbook/migrations/0027_ingredient_recipe.py b/cookbook/migrations/0027_ingredient_recipe.py
new file mode 100644
index 00000000..22502db5
--- /dev/null
+++ b/cookbook/migrations/0027_ingredient_recipe.py
@@ -0,0 +1,19 @@
+# Generated by Django 3.0.4 on 2020-03-17 17:31
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('cookbook', '0026_auto_20200219_1605'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='ingredient',
+ name='recipe',
+ field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='cookbook.Recipe'),
+ ),
+ ]
diff --git a/cookbook/models.py b/cookbook/models.py
index d3c494cd..69501111 100644
--- a/cookbook/models.py
+++ b/cookbook/models.py
@@ -127,6 +127,7 @@ class Unit(models.Model):
class Ingredient(models.Model):
name = models.CharField(unique=True, max_length=128)
+ recipe = models.ForeignKey(Recipe, null=True, blank=True, on_delete=models.SET_NULL)
def __str__(self):
return self.name
diff --git a/cookbook/tables.py b/cookbook/tables.py
index 85fdc3a9..ff7f0ca3 100644
--- a/cookbook/tables.py
+++ b/cookbook/tables.py
@@ -27,6 +27,15 @@ class KeywordTable(tables.Table):
fields = ('id', 'icon', 'name')
+class IngredientTable(tables.Table):
+ id = tables.LinkColumn('edit_ingredient', args=[A('id')])
+
+ class Meta:
+ model = Keyword
+ template_name = 'generic/table_template.html'
+ fields = ('id', 'name')
+
+
class StorageTable(tables.Table):
id = tables.LinkColumn('edit_storage', args=[A('id')])
diff --git a/cookbook/templates/recipe_view.html b/cookbook/templates/recipe_view.html
index 6cfc1256..c004bfb2 100644
--- a/cookbook/templates/recipe_view.html
+++ b/cookbook/templates/recipe_view.html
@@ -134,7 +134,13 @@
-
{{ i.ingredient.name }} |
+
+ {% if i.ingredient.recipe %}
+ {{ i.ingredient.name }}
+ {% else %}
+ {{ i.ingredient.name }}
+ {% endif %}
+ |
{% endfor %}
diff --git a/cookbook/urls.py b/cookbook/urls.py
index dcb35978..facce35e 100644
--- a/cookbook/urls.py
+++ b/cookbook/urls.py
@@ -43,7 +43,7 @@ urlpatterns = [
path('dal/unit/', dal.UnitAutocomplete.as_view(), name='dal_unit'),
]
-generic_models = (Recipe, RecipeImport, Storage, RecipeBook, MealPlan, SyncLog, Sync, Comment, RecipeBookEntry, Keyword)
+generic_models = (Recipe, RecipeImport, Storage, RecipeBook, MealPlan, SyncLog, Sync, Comment, RecipeBookEntry, Keyword, Ingredient)
for m in generic_models:
py_name = get_model_name(m)
diff --git a/cookbook/views/delete.py b/cookbook/views/delete.py
index fe595fe2..3947d8f3 100644
--- a/cookbook/views/delete.py
+++ b/cookbook/views/delete.py
@@ -4,7 +4,7 @@ from django.utils.translation import gettext as _
from django.views.generic import DeleteView
from cookbook.models import Recipe, Sync, Keyword, RecipeImport, Storage, Comment, RecipeBook, \
- RecipeBookEntry, MealPlan
+ RecipeBookEntry, MealPlan, Ingredient
from cookbook.provider.dropbox import Dropbox
from cookbook.provider.nextcloud import Nextcloud
@@ -73,6 +73,17 @@ class KeywordDelete(LoginRequiredMixin, DeleteView):
return context
+class IngredientDelete(LoginRequiredMixin, DeleteView):
+ template_name = "generic/delete_template.html"
+ model = Ingredient
+ success_url = reverse_lazy('list_ingredient')
+
+ def get_context_data(self, **kwargs):
+ context = super(IngredientDelete, self).get_context_data(**kwargs)
+ context['title'] = _("Ingredient")
+ return context
+
+
class StorageDelete(LoginRequiredMixin, DeleteView):
template_name = "generic/delete_template.html"
model = Storage
diff --git a/cookbook/views/edit.py b/cookbook/views/edit.py
index 3ebc8629..5c2f365c 100644
--- a/cookbook/views/edit.py
+++ b/cookbook/views/edit.py
@@ -15,7 +15,7 @@ from django.utils.translation import gettext as _
from django.views.generic import UpdateView
from cookbook.forms import ExternalRecipeForm, KeywordForm, StorageForm, SyncForm, InternalRecipeForm, CommentForm, \
- MealPlanForm, UnitMergeForm, IngredientMergeForm
+ MealPlanForm, UnitMergeForm, IngredientMergeForm, IngredientForm
from cookbook.models import Recipe, Sync, Keyword, RecipeImport, Storage, Comment, RecipeIngredient, RecipeBook, \
MealPlan, Unit, Ingredient
from cookbook.provider.dropbox import Dropbox
@@ -157,6 +157,22 @@ class KeywordUpdate(LoginRequiredMixin, UpdateView):
return context
+class IngredientUpdate(LoginRequiredMixin, UpdateView):
+ template_name = "generic/edit_template.html"
+ model = Ingredient
+ form_class = IngredientForm
+
+ # TODO add msg box
+
+ def get_success_url(self):
+ return reverse('edit_ingredient', kwargs={'pk': self.object.pk})
+
+ def get_context_data(self, **kwargs):
+ context = super(IngredientUpdate, self).get_context_data(**kwargs)
+ context['title'] = _("Ingredient")
+ return context
+
+
@login_required
def edit_storage(request, pk):
instance = get_object_or_404(Storage, pk=pk)
diff --git a/cookbook/views/lists.py b/cookbook/views/lists.py
index c649dc2c..38e094b7 100644
--- a/cookbook/views/lists.py
+++ b/cookbook/views/lists.py
@@ -5,8 +5,9 @@ from django.urls import reverse_lazy
from django_tables2 import RequestConfig
from django.utils.translation import gettext as _
-from cookbook.models import Keyword, SyncLog, RecipeImport, Storage
-from cookbook.tables import KeywordTable, ImportLogTable, RecipeImportTable, StorageTable
+from cookbook.filters import IngredientFilter
+from cookbook.models import Keyword, SyncLog, RecipeImport, Storage, Ingredient
+from cookbook.tables import KeywordTable, ImportLogTable, RecipeImportTable, StorageTable, IngredientTable
@login_required
@@ -34,6 +35,16 @@ def recipe_import(request):
return render(request, 'generic/list_template.html', {'title': _("Import"), 'table': table, 'import_btn': True})
+@login_required
+def ingredient(request):
+ f = IngredientFilter(request.GET, queryset=Ingredient.objects.all().order_by('pk'))
+
+ table = IngredientTable(f.qs)
+ RequestConfig(request, paginate={'per_page': 25}).configure(table)
+
+ return render(request, 'generic/list_template.html', {'title': _("Ingredients"), 'table': table, 'filter': f})
+
+
@login_required
def storage(request):
table = StorageTable(Storage.objects.all())