2010-01-01 3 views
9

Jak mogę zaktualizować obiekt z zestawu formularzy za pomocą request.POST?Zestaw Django - jak zaktualizować obiekt?

Oto mój kod i moim problemem jest to, że zawsze tworzy nowy obiekt PhoneNumber. Ale chcę zaktualizować stary obiekt PhoneNumber.

def contact_detail(request, contact_id): 
    contact = get_object_or_404(Contact, pk=contact_id) 
    phone_number_list = PhoneNumber.objects.filter(contact=contact_id) 

    if request.method == 'POST': 
     cform = ContactForm(request.POST, instance=contact) 
     #the next line is probably wrong! 
     phonenumberformset = PhoneNumberFormSet(request.POST, queryset=phone_number_list) 

     if cform.is_valid() and phonenumberformset.is_valid(): 
      phonenumber_instances = phonenumberformset.save(commit=False) 
      for phonenumber in phonenumber_instances: 
       phonenumber.contact = contact 
       phonenumber.save() 

      request.user.message_set.create(message='The contact "%s" was chanced successfully.' % contact.__str__()) 
      return HttpResponseRedirect("/crm/contacts/?oby=1") 
    else: 
     cform = ContactForm(instance=contact) 
     phonenumberformset = PhoneNumberFormSet(queryset=phone_number_list) 

    return render_to_response(
     'crm/contact_detail.html', 
     {'cform': cform, 'phonenumberformset': phonenumberformset,}, 
     context_instance = RequestContext(request), 
    ) 

Edycja: utworzenie trzech PhoneNumberForms:

PhoneNumberFormSet = modelformset_factory(PhoneNumber, max_num=3, extra=3, exclude=('contact',)) 

EDIT: rozwiązanie wykorzystujące inlineformset_factory:

@login_required 
def contact_detail(request, contact_id): 
    contact = get_object_or_404(Contact, pk=contact_id) 
    PhoneNumberInlineFormSet = inlineformset_factory(Contact, PhoneNumber, max_num=3) 

    if request.method == 'POST': 
     cform = ContactForm(request.POST, instance=contact) 
     classificationformset = ClassificationInlineFormSet(request.POST, request.FILES, instance=contact) 
     addressformset = AddressInlineFormSet(request.POST, request.FILES, instance=contact) 
     phonenumberformset = PhoneNumberInlineFormSet(request.POST, request.FILES, instance=contact) 
     if cform.is_valid() and phonenumberformset.is_valid(): 
      contact = cform.save() 
      phonenumberformset.save() 

      request.user.message_set.create(message='The contact "%s" was chanced successfully.' % contact.__str__()) 
      return HttpResponseRedirect("/crm/contacts/?oby=1") 
    else: 
     cform = ContactForm(instance=contact) 
     phonenumberformset = PhoneNumberInlineFormSet(instance=contact) 

return render_to_response(
     'crm/contact_detail.html', 
     {'cform': cform, 'phonenumberformset': phonenumberformset,}, 
     context_instance = RequestContext(request),) 

Podejście to nawet dodaje kasowania wyboru do każdego formularza inline. Łatwo i świetnie.

Odpowiedz

11

Zamiast używać modelformset_factory, użyj inlineformset_factory - patrz the documentation here - przepraszam, powinienem był skierować cię do tego na początku.

Następnie można upuścić rzeczy queryset, ponieważ inlineformset_factory dba o to, i po prostu przekazać instance argumentu (który odnosi się tutaj do modelu dominującej, czyli obiektu Contact). Nie trzeba również powtarzać poprzez jawne ustawianie atrybutu kontaktu przy zapisywaniu, ponieważ jest to ponownie obsługiwane.

+0

Dzięki ... Dużo się dziś uczę :) Pojawia się kolejny błąd również z tym podejściem: IndexError at/crm/contacts/15/ - indeks listy poza zakresem ... mam nadzieję, że pozbyłem się go inlineformset_factory –

+0

Ok wydaje się działać. Po prostu wypróbowałem to dla obiektów PhoneNumber. I wow ... Mam naprawdę fajne pole wyboru dla każdego obiektu wbudowanego .. wuhaa :) Ale jedno pytanie: czy istnieje sposób na zdefiniowanie max_num obiektów śródliniowych? Ponieważ zawsze dodaje trzy kolejne inline. –

+0

Ah ok, to samo rozwiązanie jak w przypadku "normalnych" formsetów. max_num = 3 lub dodatkowe = 0 –