"reverse editing" of generic inlines in django admin

1.3k views Asked by At

I have a django model named Event with a generic inline relation to Relationship, like this:

# models.py

class Person(models.Model):
    ...

class Role(models.Model):
    ...

class Event(models.Model):
    ...

class Relationship(models.Model):
    person = models.ForeignKey(Person)
    role = models.ForeignKey(Role)
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey("content_type", "object_id")

# admin.py

class RelationshipInline(generic.GenericTabularInline):
    model = Relationship
    extra = 0

class EventAdmin(admin.ModelAdmin):
    inlines = [RelationshipInline]

I'd like to find a way to edit the inlines not only from the event admin page, but from the people admin page too. SO far I have added the following code to display inlines in the people page too

class ReverseRelationshipInline(admin.TabularInline):
    model = Relationship

class IndividualAdmin(admin.ModelAdmin):
    inlines = [ReverseRelationshipInline]

But I get content_type and object_id fields in the form and it is not very informational for admin users since it is just references to primary keys. I would rather prefer to resolve and show the content_object(even if it is not editable, to know at list to what objects are people related to).

Any direction to recommend?

Thanks.

1

There are 1 answers

3
Danny W. Adair On

Your "ReverseRelationshipInline" has to be a GenericTabularInline, not a TabularInline. That's all :-)

UPDATE

I think I now understand what you're after, and my answer is:

You won't be able to edit the content object inline of Person, but you want to show it nicely, maybe even as a link to its change form.

Add a function to Relationship which returns such an HTML link, provide your own ModelForm to your inline and specify the fields you want, which now includes your new function value (read-only). Something like this (untested):

# models.py

from django.core import urlresolvers

class Relationship(models.Model):
    ...
    def link_content_object_changeform(self):
        obj = self.content_object
        change_url = urlresolvers.reverse(
            'admin:%s_%s_change' % (
                obj._meta.app_label,
                obj._meta.object_name.lower()
            ),
            args=(obj.id,)
        )
        return u'<a href="%s">%s</a>' % (change_url,  obj.__unicode__())
    link_content_object_changeform.allow_tags = True
    link_content_object_changeform.short_description = 'in relation to'

# admin.py

class ReverseRelationshipInlineForm(forms.ModelForm):
    class Meta:
        model = Relationship
        fields = ('person', 'role', 'link_content_object_changeform')
        readonly_fields = ('link_content_object_changeform',)

class ReverseRelationshipInline(admin.TabularInline):
    model = Relationship
    form = ReverseRelationshipInlineForm