#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 [email protected].
To post to this group, send email to [email protected].
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