Остановите вывод отдельного тега <form> в наборе форм - несколько форм в одном представлении Django
Я создаю страницу с рецептом, с деталями рецепта, ингредиентами и инструкциями. Последние несколько дней я пытался добавить список данных в форму ингредиентов, но теперь по какой-то причине форма инструкции к рецепту начала отображаться внутри собственного тега <form></form>
и поэтому не публикуется вместе с другими данными рецепта при отправке.
Я хочу иметь возможность отправлять все детали рецепта, ингредиенты и инструкции как одну форму, как я могу остановить набор форм инструкции от отображения тегов?
Inspect Image - обратите внимание, что ингредиенты рецепта не имеют тега <form>
, хотя они отображаются точно так же:
forms.py:
class RecipeForm(forms.ModelForm):
class Meta:
model = Recipe
fields = ['name', 'totalTime', 'calories', 'mainCategory']
class RecipeIngredientForm(forms.ModelForm):
ingredientName = forms.CharField(required=True)
def __init__(self, *args, **kwargs):
super(RecipeIngredientForm, self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.layout = Layout(
Div(
Div(Field("ingredientName", placeholder="Chickpeas - only write the ingredient here"), css_class='col-6 col-lg-4'),
Div(Field("quantity", placeholder="2 x 400"), css_class='col-6 col-md-4'),
Div(Field("unit", placeholder="grams"), css_class='col-5 col-md-4'),
Div(Field("description", placeholder="No added salt tins - All other information, chopped, diced, whisked!", rows='3'), css_class='col-12'),
css_class="row",
),
)
self.fields['ingredientName'].widget = ListTextWidget(data_list=Ingredient.objects.all(), name='ingredient-list')
class Meta:
model = RecipeIngredient
fields = ['ingredientName', 'quantity', 'unit', 'description']
labels = {
'ingredientName': "Ingredient",
"quantity:": "Ingredient Quantity",
"unit": "Unit",
"description:": "Ingredient Description"}
class RecipeInstructionForm(forms.ModelForm):
class Meta:
model = RecipeInstruction
fields = ['stepName', 'instructions']
labels = {'stepName': "Step Number", "instructions": "Step Instructions"}
def __init__(self, *args, **kwargs):
super(RecipeInstructionForm, self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.layout = Layout(
Div(
Div(Field("stepName"), css_class='col-4'),
Div(Field("instructions", placeholder=f"Pre-heat oven to 180°c.", rows='3'), css_class='col-12'),
css_class="row",
),
)
self.fields['instructions'].required = True
views.py:
def recipe_create_view(request):
form = RecipeForm(request.POST or None)
# Formset = modelformset_factory(Model, form=ModelForm, extra=0)
RecipeIngredientFormset = formset_factory(RecipeIngredientForm)
formset = RecipeIngredientFormset(request.POST or None)
RecipeInstructionsFormset = formset_factory(RecipeInstructionForm, extra=0)
instructionFormset = RecipeInstructionsFormset(request.POST or None, initial=[{'stepName': "Step 1"}], prefix="instruction")
context = {
"form": form,
"formset": formset,
"instructionFormset": instructionFormset
}
if request.method == "POST":
if form.is_valid() and formset.is_valid() and instructionFormset.is_valid():
parent = form.save(commit=False)
parent.user = request.user
parent.save()
# formset.save()
#recipe ingredients
for form in formset:
ingredientName = form.cleaned_data.get('ingredientName')
if ingredientName == '' or None:
pass
child = form.save(commit=False)
globalIngredient = Ingredient.objects.filter(name=ingredientName.lower()).get() # not truly global as this will return user ingredients too
if (globalIngredient):
child.ingredient = globalIngredient
else:
newIngredient = UserCreatedIngredient(user=request.user, name=ingredientName.lower())
newIngredient.save()
child.ingredient = newIngredient
child.recipe = parent
child.save()
# recipe instructions
for instructionForm in instructionFormset:
instructionChild = instructionForm.save(commit=False)
if instructionForm.instance.instructions.strip() == '':
pass
else:
instructionChild.recipe = parent
instructionChild.save()
context['message'] = 'Data saved.'
return redirect(parent.get_absolute_url())
else:
form = RecipeForm(request.POST or None)
formset = RecipeIngredientFormset()
instructionFormset = RecipeInstructionsFormset()
return render(request, "recipes/create.html", context)
create.html:
models.py:
class Recipe(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
name = models.CharField(max_length=220) # grilled chicken pasta
totalTime = models.CharField(max_length=50, blank=True, null=True)
calories = models.CharField(max_length=30, blank=True, null=True)
mainCategory = models.CharField(max_length=100, blank=True, null=True)
class Ingredient(models.Model):
name = models.CharField(max_length=220)
def __str__(self):
return self.name
class GlobalIngredient(Ingredient):
pass
class UserCreatedIngredient(Ingredient):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
class RecipeIngredient(models.Model):
recipe = models.ForeignKey(Recipe, on_delete=models.CASCADE)
ingredient = models.ForeignKey(Ingredient, null=True, on_delete=models.SET_NULL)
description = models.TextField(blank=True, null=True)
quantity = models.CharField(max_length=50, blank=True, null=True)
unit = models.CharField(max_length=50, validators=[validate_unit_of_measure], blank=True, null=True)
class RecipeInstruction(models.Model):
recipe = models.ForeignKey(Recipe, on_delete=models.CASCADE)
stepName = models.CharField(max_length=30, blank=True, null=True) # Step 1:
instructions = models.TextField(blank=True, null=True)