added ability to link recipes to ingredients

This commit is contained in:
vabene1111 2020-03-17 18:44:11 +01:00
parent a60b09e491
commit 90dbc36402
10 changed files with 94 additions and 6 deletions

View File

@ -44,3 +44,11 @@ class RecipeFilter(django_filters.FilterSet):
class Meta: class Meta:
model = Recipe model = Recipe
fields = ['name', 'keywords', 'ingredients', 'internal'] fields = ['name', 'keywords', 'ingredients', 'internal']
class IngredientFilter(django_filters.FilterSet):
name = django_filters.CharFilter(lookup_expr='icontains')
class Meta:
model = Ingredient
fields = ['name']

View File

@ -141,6 +141,13 @@ class KeywordForm(forms.ModelForm):
widgets = {'icon': EmojiPickerTextInput} widgets = {'icon': EmojiPickerTextInput}
class IngredientForm(forms.ModelForm):
class Meta:
model = Ingredient
fields = ('name', 'recipe')
widgets = {'recipe': SelectWidget}
class StorageForm(forms.ModelForm): class StorageForm(forms.ModelForm):
username = forms.CharField(widget=forms.TextInput(attrs={'autocomplete': 'new-password'}), required=False) username = forms.CharField(widget=forms.TextInput(attrs={'autocomplete': 'new-password'}), required=False)
password = forms.CharField(widget=forms.TextInput(attrs={'autocomplete': 'new-password', 'type': 'password'}), password = forms.CharField(widget=forms.TextInput(attrs={'autocomplete': 'new-password', 'type': 'password'}),

View File

@ -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'),
),
]

View File

@ -127,6 +127,7 @@ class Unit(models.Model):
class Ingredient(models.Model): class Ingredient(models.Model):
name = models.CharField(unique=True, max_length=128) name = models.CharField(unique=True, max_length=128)
recipe = models.ForeignKey(Recipe, null=True, blank=True, on_delete=models.SET_NULL)
def __str__(self): def __str__(self):
return self.name return self.name

View File

@ -27,6 +27,15 @@ class KeywordTable(tables.Table):
fields = ('id', 'icon', 'name') 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): class StorageTable(tables.Table):
id = tables.LinkColumn('edit_storage', args=[A('id')]) id = tables.LinkColumn('edit_storage', args=[A('id')])

View File

@ -134,7 +134,13 @@
</div> </div>
</td> </td>
<td style="font-size: large">{{ i.ingredient.name }}</td> <td style="font-size: large">
{% if i.ingredient.recipe %}
<a href="{% url 'view_recipe' i.ingredient.recipe.pk %}" target="_blank">{{ i.ingredient.name }}</a>
{% else %}
{{ i.ingredient.name }}
{% endif %}
</td>
</tr> </tr>
{% endfor %} {% endfor %}
</table> </table>

View File

@ -43,7 +43,7 @@ urlpatterns = [
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) generic_models = (Recipe, RecipeImport, Storage, RecipeBook, MealPlan, SyncLog, Sync, Comment, RecipeBookEntry, Keyword, Ingredient)
for m in generic_models: for m in generic_models:
py_name = get_model_name(m) py_name = get_model_name(m)

View File

@ -4,7 +4,7 @@ from django.utils.translation import gettext as _
from django.views.generic import DeleteView from django.views.generic import DeleteView
from cookbook.models import Recipe, Sync, Keyword, RecipeImport, Storage, Comment, RecipeBook, \ 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.dropbox import Dropbox
from cookbook.provider.nextcloud import Nextcloud from cookbook.provider.nextcloud import Nextcloud
@ -73,6 +73,17 @@ class KeywordDelete(LoginRequiredMixin, DeleteView):
return context 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): class StorageDelete(LoginRequiredMixin, DeleteView):
template_name = "generic/delete_template.html" template_name = "generic/delete_template.html"
model = Storage model = Storage

View File

@ -15,7 +15,7 @@ from django.utils.translation import gettext as _
from django.views.generic import UpdateView from django.views.generic import UpdateView
from cookbook.forms import ExternalRecipeForm, KeywordForm, StorageForm, SyncForm, InternalRecipeForm, CommentForm, \ 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, \ from cookbook.models import Recipe, Sync, Keyword, RecipeImport, Storage, Comment, RecipeIngredient, RecipeBook, \
MealPlan, Unit, Ingredient MealPlan, Unit, Ingredient
from cookbook.provider.dropbox import Dropbox from cookbook.provider.dropbox import Dropbox
@ -157,6 +157,22 @@ class KeywordUpdate(LoginRequiredMixin, UpdateView):
return context 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 @login_required
def edit_storage(request, pk): def edit_storage(request, pk):
instance = get_object_or_404(Storage, pk=pk) instance = get_object_or_404(Storage, pk=pk)

View File

@ -5,8 +5,9 @@ from django.urls import reverse_lazy
from django_tables2 import RequestConfig from django_tables2 import RequestConfig
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
from cookbook.models import Keyword, SyncLog, RecipeImport, Storage from cookbook.filters import IngredientFilter
from cookbook.tables import KeywordTable, ImportLogTable, RecipeImportTable, StorageTable from cookbook.models import Keyword, SyncLog, RecipeImport, Storage, Ingredient
from cookbook.tables import KeywordTable, ImportLogTable, RecipeImportTable, StorageTable, IngredientTable
@login_required @login_required
@ -34,6 +35,16 @@ def recipe_import(request):
return render(request, 'generic/list_template.html', {'title': _("Import"), 'table': table, 'import_btn': True}) 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 @login_required
def storage(request): def storage(request):
table = StorageTable(Storage.objects.all()) table = StorageTable(Storage.objects.all())