#27560: Formset.save() crashes for model with foreign key to concrete base model
-------------------------------------+-------------------------------------
     Reporter:  Lorenzo Peña         |                    Owner:  nobody
         Type:  Bug                  |                   Status:  new
    Component:  Forms                |                  Version:  1.9
     Severity:  Normal               |               Resolution:
     Keywords:  formset              |             Triage Stage:
  inline_formset                     |  Unreviewed
  inline_formsetfactory              |
    Has patch:  0                    |      Needs documentation:  0
  Needs tests:  0                    |  Patch needs improvement:  0
Easy pickings:  0                    |                    UI/UX:  0
-------------------------------------+-------------------------------------
Description changed by Lorenzo Peña:

Old description:

> {{{
> class A(models.Model):
>   pass
>
> class B(A):
>   pass
>
> class C(models.Model):
>   some_model = models.ForeignKey(SomeModel)
>   a_link = models.ForeignKey(A)
> }}}
>
> I'm using an inlineformset_factory where the parent model is SomeModel
> and the child model is C.
> When calling formset.save() I'm getting an error from
> django/forms/models.py (line 910)
>
> {{{
> 910:   pk_value = getattr(self.instance, self.fk.remote_field.field_name)
> 911:   setattr(obj, self.fk.get_attname(), getattr(pk_value, 'pk',
> pk_value))
> }}}
>
> The getattr call fails
>
> if I wrap both lines in: if hasattr(self.instance,
> self.fk.remote_field.field_name):
> it works good.
>
> Not sure if the condition is the way to fix the bug or it's just
> preventing the original cause from happening.

New description:

 Model hierharchy

 {{{
 class ConcreteBase(models.Model):
     ...


 class Descendant(ConcreteBase):
     ...
 }}}

 Master / Detail type models (e.g. Order and OrderDetail)

 {{{
 class MasterModel(models.Model):
     ...


 class DetailModel(models.Model):

     master = models.ForeignKey(MasterModel, ...)
     concrete_base = models.ForeignKey(ConcreteBase, ...)
 }}}

 Form definition

 {{{
 class MasterModelForm(forms.ModelForm):
     ...


 class DetailModelForm(forms.ModelForm):
     ...
     # master excluded from fields as will be manually added in view
     ...
 }}}

 Formset definition

 {{{
 DetailModelFormset = inlineformset_factory(MasterModel, DetailModel,
 form=DetailModelForm)
 }}}

 View definition

 {{{
 from django.views.generic.edit import CreateView #### <---- the error only
 happens on create view of MasterModel

 class MasterModelAdd(CreateView):
     model = MasterModel
     form_class = MasterModelForm
     ...

     def form_valid(self, form):
         master_instance = form.save()
         detail_formset = DetailModelFormset()(self.request.POST)
         detail_instances = detail_formset.save(commit=False) ### <------
 this line raises the error
         for detail_instance in detail_instances: ### <----- it never gets
 here
             detail_instance.master = master_instance
             detail_instance.save()

 }}}

 When calling formset.save() I'm getting an error from
 django/forms/models.py (line 910) regardless of the value of commit
 passed.

 {{{
 910:   pk_value = getattr(self.instance, self.fk.remote_field.field_name)
 911:   setattr(obj, self.fk.get_attname(), getattr(pk_value, 'pk',
 pk_value))
 }}}

 The getattr call fails

 if I wrap both lines in: {{{ if hasattr(self.instance,
 self.fk.remote_field.field_name): }}}
 it works good.

 Not sure if the condition is the way to fix the bug or it's just
 preventing the original cause from happening.

--

--
Ticket URL: <https://code.djangoproject.com/ticket/27560#comment:2>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-updates+unsubscr...@googlegroups.com.
To post to this group, send email to django-updates@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/066.5e9da8251a6beeb4381a7ae0673fdec3%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to