I want to replicate the admin functionality shown in the screenshot below on the client side. This is app is meant to cost a recipe based on the ingredients and quantity.
Find below some snippets of my code
admin.py
class RecipeIngredientInline(admin.TabularInline):
model = RecipeIngredient
extra=0
class RecipeAdmin(admin.ModelAdmin):
inlines = [RecipeIngredientInline]
admin.site.register(Recipe, RecipeAdmin)
models.py
class Ingredient(models.Model):
ingredient_name = models.CharField(max_length=255)
unit_of_measure = models.CharField(max_length=255)
price = models.DecimalField(max_digits=20, decimal_places=2)
units_size_in_package = models.DecimalField(max_digits=20, decimal_places=2)
cost_per_unit = models.DecimalField(max_digits=20, decimal_places=2)
supplier = models.CharField(max_length=255, null=True, blank=True)
create_date = models.DateTimeField(auto_now_add=True, blank=True)
edit_date = models.DateTimeField(auto_now=True, blank=True)
class Recipe(models.Model):
recipe_name = models.CharField(max_length=255)
description = models.TextField(null=True, blank=True)
photo = models.ImageField(upload_to='photos/%Y/%m/%d/', blank=True, null=True)
product_category = models.ForeignKey(ProductCategory, on_delete=models.SET_NULL, blank=True, null=True)
ingredients = models.ManyToManyField(Ingredient, through='RecipeIngredient')
is_vatable = models.BooleanField(default=False)
VAT_percentage = models.PositiveIntegerField(blank=True, null=True)
VAT = models.FloatField(blank=True, null=True)
create_date = models.DateTimeField(auto_now_add=True, blank=True)
edit_date = models.DateTimeField(auto_now=True, blank=True)
class RecipeIngredient(models.Model):
recipe = models.ForeignKey(Recipe, blank=True, null=True, on_delete=models.CASCADE)
ingredient = models.ForeignKey(Ingredient, blank=True, null=True, on_delete=models.CASCADE)
quantity = models.DecimalField(max_digits=20, decimal_places=2)
cost = models.FloatField(blank=True, null=True)
create_date = models.DateTimeField(auto_now_add=True, blank=True)
edit_date = models.DateTimeField(auto_now=True, blank=True)
forms.py
class RecipeForm(forms.ModelForm):
product_category = forms.ModelChoiceField(queryset=ProductCategory.objects.all())
class Meta:
model = Recipe
fields = ['recipe_name', 'description', 'photo', 'product_category', 'ingredients', 'is_vatable',
'VAT_percentage' ]
widgets = {
'description': forms.Textarea(
attrs={
'rows': 4,
}
),
'VAT_percentage': forms.NumberInput(
attrs={
'class': 'form-control',
}
),
}
)
class RecipeIngredientForm(forms.ModelForm):
ingredient = forms.ModelChoiceField(
queryset=Ingredient.objects.all(),
widget=forms.Select(attrs={'class': 'form-control'})
)
cost = forms.CharField(required = False)
class Meta:
Model = RecipeIngredient
fields=['ingredient', 'quantity', 'cost' ]
widgets = {
'quantity': forms.NumberInput(
attrs={
'class': 'form-control',
}
),
'cost': forms.NumberInput(
attrs={
'class': 'form-control',
}
),
}
RecipeIngredientFormset = inlineformset_factory(Recipe,
Recipe.ingredients.through,
form=RecipeIngredientForm,
extra=2,
can_delete=True
)
I am unable to add records to the parent and through table (Recipe and RecipeIngredient) so I suppose my view is not working fine. I have tried adapting the view in this question but it didn't work Add row dynamically in django formset
My current idea shown below is also not working. I am stuck and need help on where I am going wrong with the view.
views.py
from .models import Recipe, RecipeIngredient
from .forms import RecipeForm, RecipeIngredientFormset
def recipe_create_view(request):
form = RecipeForm(request.POST or None, request.FILES or None)
formset = RecipeIngredientFormset(request.POST or None)
if form.is_valid() and formset.is_valid():
recipe = form.save(commit=False)
recipe.save()
for each_form in formset:
recipe_ingredient = each_form.save(commit=False)
if recipe_ingredient.recipe is None:
recipe_ingredient.recipe = recipe
recipe_ingredient.save()
return redirect('/costing/recipes')
context = {
'form': form,
'formset': formset,
}
return render(request, 'recipes/recipe_create.html', context)