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())