django form is returning None even if something is in the input

Multi tool use


django form is returning None even if something is in the input
Hello so I've been creating a custom form int django and everything has been working the way I thought it would until i came across this problem. So I've created a form for instructions:
class InstructionForm(forms.Form):
step = forms.IntegerField(widget=forms.HiddenInput(attrs={'value':1}))
instruction = forms.CharField(widget=forms.Textarea)
Which I created a Formset for so I can let the user add as many as they want.
view.py
def create(request):
recipeForm = RecipeForm()
ingredientFormSet = formset_factory(IngredientForm, extra=4)
instructionFormSet = formset_factory(InstructionForm)
if request.method == "POST":
recipe = RecipeForm(request.POST)
ingredients_forms = ingredientFormSet(request.POST, prefix="ingredient")
instruction_forms = instructionFormSet(request.POST, prefix="instruction")
if recipe.is_valid() and ingredients_forms.is_valid() and instruction_forms.is_valid():
newRecipe = Recipe()
newRecipe.title = recipe.cleaned_data['title']
newRecipe.description = recipe.cleaned_data['description']
newRecipe.save()
for ingredient in ingredients_forms:
cd = ingredient.cleaned_data
ingredientName = cd.get('ingredient')
try:
ingredientObj = Ingredient.objects.get(name=str(ingredientName))
except Ingredient.DoesNotExist:
ingredientObj = Ingredient(name=str(ingredientName))
finally:
ingAmount = IngredientAmount()
ingAmount.amount = cd.get('amount')
ingAmount.unit = cd.get('unit')
ingredientObj.save()
ingAmount.ingredient = ingredientObj
ingAmount.recipe = newRecipe
ingAmount.save()
newRecipe.ingredients.add(ingredientObj)
newRecipe.save()
#used a counter because my initial way of doing this wont work
i=1
for instruction in instruction_forms:
cd = instruction.cleaned_data
instruct = cd.get('instruction')
# I feel like the problem is somewhere in here
instructObj = Instruction(instruction=instruct)
instructObj.step = i
instructObj.recipe = newRecipe
instructObj.save()
i+=1
else:
ingredients_forms = ingredientFormSet(prefix="ingredient")
instruction_forms = instructionFormSet(prefix="instruction")
return render(request, 'foods/createFood.html',{'recipeForm':recipeForm, 'ingredientFormSet': ingredients_forms, 'instructionFormSet': instruction_forms})
so the ingredients form and the recipe form work just fine I can add Ingredients and they'll all be added to the database. But if I add an instruction the first one works all the others won't they return None.
createFood.html
<div class="container" id="foodsPage">
<form method="POST">
{% csrf_token %}
{{recipeForm.as_p}}
{{ingredientFormSet.management_form}}
{% for ingredient in ingredientFormSet %}
<div class="fieldWrapper" id="ingForm0">
{{ingredient.amount.label_tag}}
{{ingredient.amount}}
{{ingredient.unit.label_tag}}
{{ingredient.unit}}
{{ingredient.ingredient.label_tag}}
{{ingredient.ingredient}}
</div>
{% endfor %}
<div id="addMoreIng">
</div>
<input type="button" id="addIngredient" onclick="addIngFunction()" value="Add Ingredient">
</div>
<div class="instructions">
<div id="addMoreIns">
{{instructionFormSet.management_form}}
{% for instruction in instructionFormSet %}
{{instruction.step}}
{{instruction.instruction.label_tag}}
{{instruction.instruction}}
</div>
</div>
{% endfor %}
<input type="button" id="addInstruction" onclick="addInsFunction()" value="Add instruction">
<script>
function addIngFunction(){
$('#id_ingredient-TOTAL_FORMS').val(function(i, oldval){
oldval
var html = '<div class="fieldWrapper" id="ingForm'+oldval+'">'+
'<label for="id_ingredient-'+oldval+'-amount">Amount:</label>'+
' <input type="number" name="ingredient-'+oldval+'-amount" step="any" id="id_ingredient-'+oldval+'-amount" />'+
' <label for="id_ingredient-'+oldval+'-unit">Unit:</label>'+
' <input type="text" name="ingredient-'+oldval+'-unit" maxlength="3" id="id_form-'+oldval+'-unit" />'+
' <label for="id_ingredient-'+oldval+'-ingredient">Ingredient:</label>'+
' <input type="text" name="ingredient-'+oldval+'-ingredient" maxlength="100" id="id_ingredient-'+oldval+'-ingredient" />'+
'</div>'
$('#addMoreIng').append(html)
return ++oldval;
})
}
function addInsFunction(){
$('#id_instruction-TOTAL_FORMS').val(function(i, oldval){
var val = parseInt(oldval)+1
var html = '<input type="hidden" name="instruction-'+oldval+'-step" value="'+val+'" id="id_instruction-'+oldval+'-step" />'+
'<label for="id_instruction-'+oldval+'-instruction">Instruction:</label>'+
'<textarea name="instruction-'+oldval+'-instruction" cols="40" rows="10" id="id_instruction-'+oldval+'-instruction">'+
'</textarea>'
$('#addMoreIns').append(html)
return ++oldval;
})
}
</script>
<input type="submit" value="submit recipe">
</form>
</div>
I can't figure out why any of the added instructions return None.
can anyone help me out?
1 Answer
1
You are closing two div
s inside the {% for instruction in instructionFormSet %}
but they should be closed outside the loop. I haven't checked it, but this may close more tags when parsed by the browser into the DOM than intended including implicitly the form
tag.
div
{% for instruction in instructionFormSet %}
form
This could lead to some inputs not being inside the form anymore (according to browser DOM) and therefore not being submitted by the browser in the POST request. Try fixing your HTML.
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
Thank you so much, I feel stupid that the only problem was the html
– Aaron McCommon
yesterday