I have this code, the contactForm work well but the socialProofForm just duplicate all db entries at save, instead of update the existing query, someone can help pls, i have 3 days with this bug i think may django bug
# django
from django.utils.translation import gettext_lazy as _
from django.shortcuts import render, redirect, get_object_or_404
from django.forms.models import modelformset_factory
from django.contrib.auth.decorators import login_required
# forms
from ..forms.files import ImageForm
from ..forms.business import BusinessForm, PremiseForm, PositionForm, OpenDaysForm, OpenDaysSForm, BusinessHours, SocialProofForm
from ..forms.general import ContactForm, GeolocationForm
# models
from ..models.business import Business
from ..models.premises import Premise, Position, OpenDays, SocialProof
from ..models.general import Contact
contactForm = modelformset_factory(
Contact,
form=ContactForm,
extra=8,
max_num=8
)
socialProofForm = modelformset_factory(
SocialProof,
form=SocialProofForm,
extra=0,
max_num=3
)
def GenerateForms(request, business, premises):
premisesF = [{}]
for i, premise in enumerate(premises):
# multiple other forms
premisesF[i]['contact'] = contactForm(
request.POST or None,
queryset=premise.contact.all(),
prefix=f'{i}_contact',
)
premisesF[i]['proof'] = socialProofForm(
request.POST or None,
queryset=premise.social_proof.all(),
prefix=f'{i}_proof',
)
return {
'premisesF': premisesF
}
def BusinessAdminView(request, business_id):
business = get_object_or_404(Business, id=business_id)
premises = Premise.objects.filter(business=business.pk).order_by('name')
forms = GenerateForms(request, business, premises)
premisesF = forms['premisesF']
if request.POST:
for i, premiseF in enumerate(premisesF):
premise = premises[i]
# multiple other forms
if premiseF['proof'].is_valid():
formDirty = True
for form in premiseF['proof']:
if form.empty_permitted and not form.has_changed():
continue
# this ever duplicate the existed element with the instance data
form.save()
if not premise.social_proof.filter(pk=form.instance.pk).exists():
premise.social_proof.add(form.instance)
if premiseF['contact'].is_valid():
formDirty = True
for cont in premiseF['contact']:
# all here work well
if cont.empty_permitted and not cont.has_changed():
continue
# this just update the modified element as spected
cont.save()
if not premise.contact.filter(id=cont.instance.id).exists():
premise.contact.add(cont.instance)
if (formDirty):
return redirect(request.path)
return render(request, 'templates/business.html', {
'premisesF': forms['premisesF'],
})
View
{{ premise.proof.management_form }}
{% for sp in premise.proof %}
{% for hidden in sp.hidden_fields %}{{ hidden }}{% endfor %}
<div class="input-placeholder-textarea" data-placeholder="{{ sp.title.name }}">{{ sp.title }}</div>
<div class="input-placeholder-textarea" data-placeholder="{{ sp.content.name }}">{{ sp.content }}</div>
{% endfor %}
Forms
class SocialProofForm(ModelForm):
class Meta:
model = SocialProof
fields = ('title', 'content')
class OpenDaysForm(ModelForm):
class Meta:
model = OpenDays
fields = '__all__'