Reputation: 125
Hello I have got question I have made modelformset_factory and in options I have choosen can_delete = True and now I don't know how to delete marked objects as 'DELETE' : True to delete them from database. I was trying to do this in some ways and it didnt work. I was looking for it also in django formsetmodels documentation but this didnt help me. With this option can_delete = True I get additional checkbox in my html page Delete and marking him only prints me in console on print: {'username': 'sw', 'email': '[email protected]', 'city': 'ss', 'code': 12345, 'id': , 'DELETE': False}
Saving forms to database is working but I dont know how to delete marked forms from database.
I would be very thankful for every help.
I have made modelformset_factory from model in models.py
class TestModel(models.Model):
username = models.CharField(max_length=120)
email = models.EmailField()
city = models.CharField(max_length=120)
code = models.IntegerField()
#W admin panelu za miast TestModel object bedzie username
def __str__(self):
return self.username
Then I have added in my views.py function:
def django_modelformset(request):
TestModelFormset = modelformset_factory(TestModel, fields=['username', 'email', "city",
"code"], extra=1, can_delete=True)
formset = TestModelFormset(request.POST or None)
if formset.is_valid():
for form in formset:
print(form)
print(form.cleaned_data)
form.save()
context = {"formset": formset}
return render(request, "modelformset.html", context)
My modelformset.html looks like this:
<form method="POST" action="">
{% csrf_token %}
{{ formset.management_form}}
{% for form in formset %}
<div>
{{ form.as_p }}
<hr/>
</div>
{% endfor %}
<input type="submit" value="Save">
Upvotes: 4
Views: 3094
Reputation: 371
It's work for me
view.py
Blog_MetaFormSet = modelformset_factory(Metas, form=MetaForm, extra=0, can_delete=True)
Blog_MetaQuerySet = Metas.objects.filter(blog=blog_obj).order_by('created_at')
contex={
"blog_meta_formset": Blog_MetaFormSet(request.POST,queryset=Blog_MetaQuerySet),
}
if blog_meta_formset.is_valid():
for metaform in blog_meta_formset:
meta_obj = metaform.save(commit=False)
meta_obj.blog = blog_obj
if metaform.cleaned_data["DELETE"]==True:
meta_obj.delete()
else:
meta_obj.save()
In Templates
<div class="row">
<div id="cfield-form-list"> {{ blog_meta_formset.management_form }} {% for meta_form in blog_meta_formset %}
<div id="form-{{forloop.counter0}}" class="cfield-form xrow">
<div class="col-md-12 mb-3">
<div class="row d-flex align-items-center">
<div class="col-md-4">
<label class="form-label">Name</label> {{ meta_form.title|attr:"class:form-control"|attr:"type:text" }} </div>
<div class="col-md-4">
<label class="form-label">Value</label> {{ meta_form.value|attr:"class:form-control"|attr:"rows:2" }} </div>
<div class="col-md-4">
<div class="form-check custom-checkbox mb-3 checkbox-primary"> {{ meta_form.DELETE|attr:"class:form-check-input"|attr:"type:checkbox" }}
<label class="form-check-label" for="customCheckBox2">Delete</label>
</div>
</div>
</div>
</div> {{meta_form.id}} </div> {% endfor %} </div>
<div id="empty_form" class="hidden">
<div class="col-md-12 mb-3">
<div class="row d-flex align-items-center">
<div class="col-md-4">
<label class="form-label">Name</label> {{ blog_meta_formset.empty_form.title|attr:"type:text"|attr:"class:form-control" }} </div>
<div class="col-md-4">
<label class="form-label">Value</label> {{ blog_meta_formset.empty_form.value|attr:"class:form-control"|attr:"rows:2" }} </div>
<div class="col-md-4">
<div class="form-check custom-checkbox mb-3 checkbox-primary"> {{ blog_meta_formset.empty_form.DELETE|attr:"class:form-check-input"|attr:"type:checkbox" }}
<label class="form-check-label" for="customCheckBox2">Delete</label>
</div>
</div>
<div class="col-md-4">
<button type="button" class="btn btn-danger remove_cfield" rel="">Delete</button>
</div>
</div>
</div>
</div>
<div class="col-md-12">
<button type="button" id="add-cfield" class="btn btn-primary mb-3 mt-3 ">Add Custom Field</button>
</div>
</div>
In js
const totalNewForms = document.getElementById('id_form-TOTAL_FORMS')
const addMoreBtn = document.getElementById('add-cfield')
addMoreBtn.addEventListener('click',add_new_form)
function add_new_form(event){
if (event){
event.preventDefault()
}
const currentCF_Forms = document.getElementsByClassName('cfield-form')
console.log(currentCF_Forms)
const currentCF_FormCount = currentCF_Forms.length //+ 1
const formCopyTarget = document.getElementById('cfield-form-list')
const copyEmptyFormEl = document.getElementById('empty_form').cloneNode(true)
//remove class hidden
copyEmptyFormEl.setAttribute('class','cfield-form xrow')
copyEmptyFormEl.setAttribute('id',`form-${currentCF_FormCount}`)
const regex = new RegExp('__prefix__','g')
copyEmptyFormEl.innerHTML = copyEmptyFormEl.innerHTML.replace(regex,currentCF_FormCount)
totalNewForms.setAttribute('value', currentCF_FormCount +1)
//now add new empty form element to our html form
formCopyTarget.append(copyEmptyFormEl)
Upvotes: 0
Reputation: 697
I haven't personally had to do this, but from the docs it seems you have a few options.
Call save on the formset instead of each form.
if formset.is_valid():
formset.save()
If you must loop through each form you could something like this.
if formset.is_valid():
for form in formset:
print(form.cleaned_data)
if form.cleaned_data["DELETE"]:
# Do what you want with the form data
# i.e. get the object from the database and delete it.
else:
form.save()
Loop through the deleted forms separately.
if formset.is_valid():
forms = formset.save(commit=False)
for object in formset.deleted_objects:
object.delete()
Upvotes: 7