Opened 16 years ago

Closed 16 years ago

Last modified 16 years ago

#9498 closed (fixed)

generic inline formsets: object has no attribute 'fk'

Reported by: Fred Bartle Owned by: Brian Rosner
Component: Contrib apps Version: dev
Severity: Keywords: generic inline formsets
Cc: Carl Meyer, Ben Spaulding Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

As of r9297, which django.contrib.admin.helpers now utilizes formset.fk, generic inline formsets now break attempting to access formset.fk. Attached is a simple fix, though I suspect there's more work to be done with generic and r9297.

Attachments (4)

generic.py.r9329.diff (504 bytes ) - added by Fred Bartle 16 years ago.
generic.py.r9329_2.diff (728 bytes ) - added by markus _forgot_ evigo _spam_ net 16 years ago.
generic.py_helpers.py_r9329.diff (892 bytes ) - added by markus _uploading_ evigo _patch_ net 16 years ago.
generic_inline_tests.diff (6.1 KB ) - added by Daniel Roseman 16 years ago.

Download all attachments as: .zip

Change History (14)

by Fred Bartle, 16 years ago

Attachment: generic.py.r9329.diff added

comment:1 by Fred Bartle, 16 years ago

Has patch: set
Needs tests: set

comment:2 by Fred Bartle, 16 years ago

Here's a basic example:

class Attribute(models.Model):
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey('content_type', 'object_id')
    key = models.CharField(max_length=30)
    value = models.CharField(max_length=30)

class MyModel(models.Model):
    name = models.CharField(max_length=30)
    attributes = generic.GenericRelation(Attribute)


class AttributeInline(generic.GenericTabularInline):
    model = Attribute

class MyModelAdmin(models.Model):
    inlines = [AttributeInline]

comment:3 by Brian Rosner, 16 years ago

Owner: changed from nobody to Brian Rosner
Status: newassigned
Triage Stage: UnreviewedAccepted

comment:4 by markus@…, 16 years ago

applying the patch helped, but directly showed a new bug:

http://nopaste.com/p/aJeKlSyvj

looking into contrib/contenttypes/generic.py I found this:

if exclude is not None: 
    exclude.extend([ct_field.name, fk_field.name])
else: 
    exclude = [ct_field.name, fk_field.name]

makes no sense to me, but i'm not the architect ;)
So i'm attaching another patch, which includes the first and
deletes the whole "else" - for me this fixes GenericTabularInline

by markus _forgot_ evigo _spam_ net, 16 years ago

Attachment: generic.py.r9329_2.diff added

comment:5 by markus _presents_a_better_ evigo _solution_ net, 16 years ago

so once again:

after some testing i've seen, that those lines:

if exclude is not None:
    exclude.extend({ct_field.name, fk_field.name})
else:
    exclude = [ct_field.name, fk_field.name]

Are indeed _not_ useless! It's absolutly clear (now - for me - finally), that
we of course don't need the ForeignKey in a GenericInlineFormSet, because it's
clear that we set the ForeignKey according the Model we are "inlining". So without
the "else" from the snippet, I always had a content_type and object_id field in
my inline-form, what seems to be a new-self-produced-bug - means: re-add those two
lines and restart searching, why I always get: http://nopaste.com/p/aJeKlSyvj

The problem with this is, the fk_field is beeing called directly from the template,
so there is no way to avoid beeing asked for the fk_field-widget. As mentioned before,
we have absolutly no need for the fk-field, as it gets set automaticly by the parent
model. So i just looked for the output-method for fk_field - in contrib/admin/helpers.py:

def fk_field(self):
        return AdminField(self.form, self.formset.fk.name, False)

inside "InlineAdminForm", means for me only inlined-models come across this form,
so it's painless to just change it to:

def fk_field(self):
    try:
        return AdminField(self.form, self.formset.fk.name, False)
    except KeyError, e:
        return ""

This actually is just a silent failure, which still works if needed.
(Isn't this anyway planned/recommended for template-parsing?)

So there is another file attached, including this and the first patch.
Do _NOT_ use the second patch, it's more an ugly hack than a solution ;)

hope i could help,
greets

by markus _uploading_ evigo _patch_ net, 16 years ago

comment:6 by Carl Meyer, 16 years ago

Cc: Carl Meyer added

comment:7 by Ben Spaulding, 16 years ago

Cc: Ben Spaulding added

by Daniel Roseman, 16 years ago

Attachment: generic_inline_tests.diff added

comment:8 by Daniel Roseman, 16 years ago

Needs tests: unset

Patch that adds regression tests for this problem.

comment:9 by Brian Rosner, 16 years ago

Resolution: fixed
Status: assignedclosed

(In [9413]) [1.0.X] Fixed #9498 -- Handle a formset correctly when the foreign key is not available (for now).

This case pops up with generic foreign key inlines after [9297]. Added tests
to handle future regressions with generic foreign key inlines in the admin.

Thanks markus and danielr for patches.

Backport of [9412] from trunk.

comment:10 by Brian Rosner, 16 years ago

This was also applied on trunk in [9412] -- dang post-commit hook :)

Note: See TracTickets for help on using tickets.
Back to Top