added ability to link recipes to ingredients
This commit is contained in:
parent
a60b09e491
commit
90dbc36402
@ -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']
|
||||
|
@ -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'}),
|
||||
|
19
cookbook/migrations/0027_ingredient_recipe.py
Normal file
19
cookbook/migrations/0027_ingredient_recipe.py
Normal 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'),
|
||||
),
|
||||
]
|
@ -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
|
||||
|
@ -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')])
|
||||
|
||||
|
@ -134,7 +134,13 @@
|
||||
</div>
|
||||
|
||||
</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>
|
||||
{% endfor %}
|
||||
</table>
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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())
|
||||
|
Loading…
Reference in New Issue
Block a user