Django BaseGenericInlineFormSet forms not inheriting FormSet instance as form instance related_object -


i'm using django 1.8 , have image class looks this:

# `child` class class image(models.model):     content_type = models.foreignkey(contenttype)     object_id = models.positiveintegerfield()      related_object = genericforeignkey('content_type', 'object_id')      image = models.imagefield(...)      def clean(self):         related_class = self.content_type.model_class()         # validation relies on related_class 

and "parent" class has genericrelation it:

# `parent` class class product(models.model):     ...     images = genericrelation('image') 

this (simplified) view:

from django.shortcuts import render, get_object_or_404 django.views.generic import view django.contrib.contenttypes.forms import generic_inlineformset_factory  productimageinlineformset = generic_inlineformset_factory(     image, extra=1)  class productimageview(view):     ...     def post(self, request, id):         product = get_object_or_404(product.objects.by_id(id))         image_formset = productimageinlineformset(             request.post, request.files, instance=product)         # shouldn't need following 2 lines ->         # form in image_formset:         #     form.instance.related_object = product         import ipdb; ipdb.set_trace()          if image_formset.is_valid():             image_formset.save()          return render(request, self.template,                       context={'cid': id, 'formset': image_formset}) 

when inspect formset in ipdb, get:

ipdb> image_formset.forms[0].instance.related_object none true 

this causing problems because when image.clean() error:

django.db.models.fields.related.relatedobjectdoesnotexist: image has no content_type. 

if uncomment 2 lines mentioned don't need, works , don't error anymore. isn't automatic linking of forms models , related models whole point of using basegenericinlineformset? if have manually hack imageform instances , attach product instance related_object, might use simple modelformset. missing something?

update

if comment image.clean out, code works without manual attachment of related objects. means basegenericinlineformset handle linking after all, after calls clean on child model, not ok considering model.clean "should used provide custom model validation". i'm taking @ django source haven't yet figured out linking. tips welcome.

update 2

apparently linking done in inlineformset save_new method:

def save_new(self, form, commit=true):     setattr(form.instance, self.ct_field.get_attname(),         contenttype.objects.get_for_model(self.instance).pk)     setattr(form.instance, self.ct_fk_field.get_attname(),         self.instance.pk)     return form.save(commit=commit) 

https://github.com/django/django/blob/master/django/contrib/contenttypes/forms.py#l46

as experiment, i've moved code custom _construct_form method:

 def _construct_form(self, i, **kwargs):      form = super()._construct_form(i, **kwargs)      setattr(form.instance, self.ct_field.get_attname(),          contenttype.objects.get_for_model(self.instance).pk)      setattr(form.instance, self.ct_fk_field.get_attname(),          self.instance.pk)      return form 

it solved problem. way don't have manual linking. haven't run tests or written patch first step if decides in future (perhaps myself @ 1 point).

for i'm keeping solution manual linking though. don't want work hacked version of django.

since i've got no feedback, i'll assume it's django bug, , seems case. filed ticket here: https://code.djangoproject.com/ticket/25488

the solution until solved either suggested earlier (i.e. iterating on forms in view , linking them product manually) or using fixed formset class, like:

class fixedbasegenericinlineformset(basegenericinlineformset):     def _construct_form(self, i, **kwargs):         form = super()._construct_form(i, **kwargs)         setattr(form.instance, self.ct_field.get_attname(),             contenttype.objects.get_for_model(self.instance).pk)         setattr(form.instance, self.ct_fk_field.get_attname(),             self.instance.pk)         return form  productimageinlineformset = generic_inlineformset_factory(     image,     form=productimageform,     formset=fixedbasegenericinlineformset,     extra=1 ) 

Comments

Popular posts from this blog

html - Outlook 2010 Anchor (url/address/link) -

javascript - Why does running this loop 9 times take 100x longer than running it 8 times? -

Getting gateway time-out Rails app with Nginx + Puma running on Digital Ocean -