id,summary,reporter,owner,description,type,status,component,version,severity,resolution,keywords,cc,stage,has_patch,needs_docs,needs_tests,needs_better_patch,easy,ui_ux 18357,BaseGenericInlineFormSet in Django Admin does not set generic foreign key fields when constructing form,buettgenbach@…,nobody,"For a BaseInlineFormSet in _construct_form the fk value is set in order to do validation. {{{ def _construct_form(self, i, **kwargs): ... # Set the fk value here so that the form can do it's validation. setattr(form.instance, self.fk.get_attname(), self.instance.pk) return form }}} Something similar is missing for BaseGenericInlineFormSet. Actually it has been removed in [https://github.com/django/django/commit/856a39e841080abc34e8ae3bb2b20f780c33762d#L0R329]. As a consequence during model based cleaning the generic foreign key attribute cannot be accessed/cleaned because it is not set. Assume the following fictional code: {{{ class Poll(models.Model): question = models.CharField(max_length=200) pub_date = models.DateTimeField('date published') class GenericChoice(models.Model): content_type = models.ForeignKey(ContentType) content_id = models.PositiveIntegerField() content = generic.GenericForeignKey('content_type', 'content_id') choice = models.CharField(max_length=200) votes = models.IntegerField() def clean(self): if self.votes > 10 and self.content.question == 'Don't allow more than 10 votes': raise ValidationError('Test') }}} This results in an NoneType error since self.content is None. With something like this in BaseGenericInlineFormSet it could be fixed: {{{ def _construct_form(self, i, **kwargs): # Avoid a circular import. from django.contrib.contenttypes.models import ContentType form = super(BaseGenericInlineFormSet, self)._construct_form(i, **kwargs) # if self.save_as_new: # # Remove the key from the form's data, we are only creating new instances. # form.data[form.add_prefix(self.ct_fk_field.name)] = None # form.data[form.add_prefix(self.ct_field.name)] = None # Set the GenericForeignKey value here so that the form can do its validation. setattr(form.instance, self.ct_fk_field.attname, self.instance.pk) setattr(form.instance, self.ct_field.attname, ContentType.objects.get_for_model(self.instance).pk) return form }}} But this would only fix those cases where the parent model already exists (Admin edit). If the parent does not exist (for example when creating a new Poll with some GenricChoice inline sets) the generic foreign key field cannot be accessed since content_id is not set (and the _cache_content is not set, too). Using a simple BaseInlineFormSet this is achieved by setting the foreing key object through the InlineForeignKeyField which is instantiated with the foreign key object during add_fields in BaseInlineFormSet. ",Bug,new,contrib.contenttypes,1.3,Normal,,,,Accepted,0,0,0,0,0,0