3

I want to update a formset that can have different entries. I will able to present the formset pre populated with the correct data, however I'm doing something wrong since it does not update but creates a new instance..

I'm seen inlineformset_factory however since I'm passing more than one value to the formset I was not able to work with it..

If anyone has any pointer I will truly appreciate it!

views.py

    epis = Contact.objects.filter(episode=int(value))

    ContactSet = formset_factory(Contact1Form, extra=len(epis), max_num=len(epis))
    if request.method =='POST':
        formset = ContactSet(request.POST)
        if formset.is_valid():
            for form in formset.forms:
                age = form.cleaned_data['age']
                bcg = form.cleaned_data['bcg_scar']
                radio = form.cleaned_data['radiology']

                profile = form.save(commit=False)
                for i in epis:
                    profile.contact = i

                fields = {'age': age, 'bcg_scar': bcg, 'radiology': radio}

                for key, value in fields.items():
                    if value == u'':
                        setattr(profile, key, None)
                    else:
                        setattr(profile, key, value)

                profile.save()
        return render_to_response('success.html', {'location': location})
    else:
        dic = []
        for c in epis:
            aux = {}
            for f in c._meta.fields:
                if f.name not in ['contact_id', 'episode']:
                    aux[f.name] = getattr(c, f.name)
            dic.append(aux)

        formset = ContactSet(initial=dic)
    return render_to_response('form.html',
            {   'msg': msg,
                'location': location,
                'formset': formset,
                'word': word })

forms.py

  class ContactForm(forms.ModelForm):
        affinity = forms.ModelChoiceField(queryset=Affinity.objects.all(),
                  label=ugettext("Affinity"))
        age = forms.IntegerField(label=ugettext("Age when diagnosed"),
                  required=False)

        MAYBECHOICES = (
            ('', '---------'),
            (ugettext('Yes'), ugettext('Yes')),
            (ugettext('No'), ugettext('No')))

        bcg_scar = forms.ChoiceField(choices=MAYBECHOICES, label=ugettext(
                  "BCG scar"), required=False)
        radiology = forms.ModelChoiceField(queryset=Radiology.objects.all(),
                 label=ugettext("Radiology"),required=False)

    class Meta:
         model = Contact

Any pointers would be of great help!

EDIT

After some suggestions from Catherine

  formset = ContactSet(request.POST, queryset=epis)

which gave me this error:

  __init__() got an unexpected keyword argument 'queryset'

I try changing

 from django.forms.models import modelformset_factory
 ContactSet = modelformset_factory(Contact1Form, extra=len(epis), max_num=len(epis))

and this error appeared:

'ModelFormOptions' object has no attribute 'many_to_many'

and then saw that to solve this error I will need to use the name of the model instead.

ContactSet = modelformset_factory(Contact, extra=len(epis), max_num=len(epis))

and I get a MultiValueDictKeyError

psoares
  • 4,733
  • 7
  • 41
  • 55

2 Answers2

0

You just forget to add instance in the formset,

 if request.method =='POST':
    formset = ContactSet(request.POST, queryset=epis)
    if formset.is_valid():
catherine
  • 22,492
  • 12
  • 61
  • 85
  • But epis is a list of objects. I think i need to pass to instance only one object – psoares Apr 08 '13 at 07:02
  • I don't know which object connect to your ContactSet form that's why I'm guessing it's epis. But the main point here is you forgot to add `instance` which is equal to the object you want to update – catherine Apr 08 '13 at 07:09
  • But I'm using formset since I want to update several objects. epis could be this: [, , , ], which will show 4 different forms with the information of those contacts. My problem is that when I submit it creates a new object instead of update. I've tried your suggestion but it gives me this error: __init__() got an unexpected keyword argument 'instance' – psoares Apr 08 '13 at 08:42
  • sorry I forgot you use formset. Replace it with `queryset`. Answer updated – catherine Apr 08 '13 at 08:55
  • I've tried your solution however I'm still dealing with some errors. Can you please see my edit? if you have any idea how to solve this. Thank you – psoares Apr 08 '13 at 09:17
  • I've tried to use exclude like in the documentation: AuthorFormSet = modelformset_factory(Author, exclude=('birth_date',)) since contact_id is not show. Could this be the problem? "Key 'form-0-contact_id' not found in – psoares Apr 08 '13 at 09:23
  • Rather than use modelformset_factory, use inlineformset_factory https://docs.djangoproject.com/en/1.1/topics/forms/modelforms/#inline-formsets. In that way, you can now use the instance method – catherine Apr 08 '13 at 09:36
  • before asking this question I tried it but I not sure if it is possible since with instance and inline you pass something with get: author = Author.objects.get(name=u'Mike Royko') and I'm passing a list of objects hence the formset.. – psoares Apr 08 '13 at 10:05
  • I got it! I only need to pass the instance of episode and it will give all the ids with the same episode :) thank you for your help – psoares Apr 08 '13 at 14:29
0
MyFormSet = modelformset_factory(ModelName, form=MyForm)
qs = ModelName.objects.filter(user=request.user)
formset = MyFormSet(queryset=qs)
boldnik
  • 2,547
  • 2
  • 27
  • 32