Opened 9 years ago
Closed 9 years ago
#25488 closed Bug (duplicate)
BaseGenericInlineFormSet runs validation methods before linking form instances to their related object
Reported by: | Ariel Pontes | Owned by: | nobody |
---|---|---|---|
Component: | contrib.contenttypes | Version: | 1.8 |
Severity: | Normal | Keywords: | BaseGenericInlineFormSet clean validation |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
I have a generic inline FormSet class generated like this:
ProductImageInlineFormset = generic_inlineformset_factory( Image, form=ProductImageForm, extra=1)
and initialized like this:
product = get_object_or_404(Product.objects.by_id(id)) image_formset = ProductImageInlineFormset( request.POST, request.FILES, instance=product)
When the individual forms that compose the FormSet are initialized, the "product" object is not linked to their instances. This is only done in the BaseGenericInlineFormSet.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)
This causes problem when the Image class needs to do validation across fields:
class Image(models.Model): ... def clean(self): related_class = self.content_type.model_class() print(self.content_type.model_class())
The above code results in the following error when trying to save ProductImageInlineFormsets:
django.db.models.fields.related.RelatedObjectDoesNotExist: Image has no content_type.
The linking of Image to Product should be done in the form initialization instead. At first sight, after a quick experiment, overriding the _construct_form
instead of the save_new
seems to solve the problem:
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
Change History (3)
comment:1 by , 9 years ago
comment:2 by , 9 years ago
The problem described is indeed very similar, but the example given was of a simple ModelFormset, not Generic or Inline. I installed stable/1.8.x
and the problem persists. In a way it makes sense, I honestly don't understand how that commit would have solved the problem. It must solve the problem for ModelFormSet only, not BaseGenericInlineFormSet.
comment:3 by , 9 years ago
Resolution: | → duplicate |
---|---|
Status: | new → closed |
Thanks for looking into it. Upon further investigation, I think this a duplicate of #19255. If you'd like to submit a patch with tests, that will help move the issue forward. Thanks!
It might be a duplicate of #25431 -- could you check if the problem exists on the
stable/1.8.x
branch, which will be soon released as 1.8.5?