2010-01-01 20 views
9

¿Cómo puedo actualizar un objeto desde un formset usando request.POST?formset Django - cómo actualizar un objeto?

Aquí está mi código y mi problema es que esto siempre crea un nuevo objeto PhoneNumber. Pero quiero actualizar el antiguo objeto 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), 
    ) 

Edit: crear tres PhoneNumberForms:

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

Editar: la solución usando 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),) 

Este enfoque aún añade una casilla de verificación de eliminación para cada formulario en línea. Fácil y genial

Respuesta

11

En lugar de usar modelformset_factory, use inlineformset_factory - consulte the documentation here - disculpe, debería haberle señalado eso inicialmente.

A continuación, se puede soltar el material queryset, ya inlineformset_factory se encarga de eso, y sólo tiene que pasar el argumento instance (que en este caso se refiere al modelo padres, es decir, el objeto Contact). Tampoco necesitará repetir el ajuste explícitamente en el atributo de contacto al guardar, ya que una vez más eso se solucionó.

+0

Gracias ... Aprendo mucho hoy :) Recibo otro error también con este enfoque: IndexError at/crm/contacts/15/ - índice de lista fuera de rango ... con suerte me deshago de él con inlineformset_factory –

+0

Ok parece funcionar. Acabo de probarlo para los objetos PhoneNumber. Y vaya ... Obtuve una casilla de verificación de eliminación muy buena para cada objeto en línea ... wuhaa :) Pero una pregunta: ¿Hay alguna forma de definir un max_num de objetos en línea? Como siempre agrega tres líneas más. –

+0

Ah ok, la misma solución que para los conjuntos de formularios "normales". max_num = 3 o extra = 0 –

Cuestiones relacionadas