حتى تستطيع إضافة حقل بشكل ألي و ديناميكي يجب إستخدام بعض من JS جافا سكربت سكون الشرح على 3 خطوات أولا ما سوف تفعله في ملف templates لماذا يجب إستخدام JS في المتصفح لتعديل على elements أو عناصر HTML بدون إعادة تحميل الصفحة يجب استخدام لغة برمجة تعمل على المتصفح نفسه.
مثال على الفكرة المطلوبة
أولاً views.py
from django.contrib.auth.decorators import login_required
from django.forms.models import modelformset_factory # model form for querysets
from django.shortcuts import redirect, render, get_object_or_404
from .forms import RecipeForm, RecipeIngredientForm
from .models import Recipe, RecipeIngredient
@login_required
def recipe_update_view(request, id=None):
obj = get_object_or_404(Recipe, id=id, user=request.user)
form = RecipeForm(request.POST or None, instance=obj)
# Formset = modelformset_factory(Model, form=ModelForm, extra=0)
RecipeIngredientFormset = modelformset_factory(RecipeIngredient, form=RecipeIngredientForm, extra=0)
qs = obj.recipeingredient_set.all() # []
formset = RecipeIngredientFormset(request.POST or None, queryset=qs)
context = {
"form": form,
"formset": formset,
"object": obj
}
if all([form.is_valid(), formset.is_valid()]):
parent = form.save(commit=False)
parent.save()
# formset.save()
for form in formset:
child = form.save(commit=False)
child.recipe = parent
child.save()
context['message'] = 'Data saved.'
return render(request, "recipes/create-update.html", context)
ثانياً: recipes/create-update.html: templates
أولاً جزء HTML
{% if formset %}
<h3>Ingredients</h3>
{{ formset.management_form }}
<div id='ingredient-form-list'>
{% for form in formset %}
<div class='ingredient-form'>
{{ form.as_p }}
</div>
{% endfor %}
</div>
<div id='empty-form' class='hidden'>{{ formset.empty_form.as_p }}</div>
<button id='add-more' type='button'>Add more</button>
{% endif %}
<button style='margin-top:10px;' type='submit' >Save</button>
</form>
</div>
والأن مع جزء JS وسيكون في نفس ملف HTML في النهاية.
<script>
const addMoreBtn = document.getElementById('add-more')
const totalNewForms = document.getElementById('id_form-TOTAL_FORMS')
addMoreBtn.addEventListener('click', add_new_form)
function add_new_form(event) {
if (event) {
event.preventDefault()
}
const currentIngredientForms = document.getElementsByClassName('ingredient-form')
const currentFormCount = currentIngredientForms.length // + 1
const formCopyTarget = document.getElementById('ingredient-form-list')
const copyEmptyFormEl = document.getElementById('empty-form').cloneNode(true)
copyEmptyFormEl.setAttribute('class', 'ingredient-form')
copyEmptyFormEl.setAttribute('id', `form-${currentFormCount}`)
const regex = new RegExp('__prefix__', 'g')
copyEmptyFormEl.innerHTML = copyEmptyFormEl.innerHTML.replace(regex, currentFormCount)
totalNewForms.setAttribute('value', currentFormCount + 1)
// now add new empty form element to our html form
formCopyTarget.append(copyEmptyFormEl)
}
</script>
{% endblock content %}
قد يكون ليس من السهل فهم كل شئ في كود JS لكن ما يقوم به كود SCRIPT هو نسخ أحد العناصر من HTML عند حدوث حدث click على الزر Add more
و في نفس الوقت يتم التعديل على بعض Attribute في عناصر Html الجديدة و بعد القيام بأي حفظ للبيانات سيقوم بعرض ما تم حفظه اقرأ الأكواد جيداً يستحسن أن يكون لديك فكرة عامة عن JS و أتوقع ان يكون الكود مفهوم بالنسبة لك وهذا المثال ليساعدك على حل مشكلة الخاصة بك