Opened 10 years ago
Closed 10 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 , 10 years ago
comment:2 by , 10 years ago
Replying to timgraham:
It might be a duplicate of #25431 -- could you check if the problem exists on the
stable/1.8.xbranch, which will be soon released as 1.8.5?
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 , 10 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.xbranch, which will be soon released as 1.8.5?