14

I'm trying to customize and many to many inline in the django Admin, but I'm not able to display the fields of the underlying models.

Here's a simplified example. Maybe you can tell me how to reference them?

Here are my models:

class Clown(models.Model):
    name = models.CharField(max_length=255)
    def edit_link(self):
        return ...

class Circus(models.Model):
    clowns = models.ManyToManyField(Clown, blank=True, through='WorkedAt')
    name = models.CharField(max_length=255)

class WorkedAt(models.Model):
    clown = models.ForeignKey(Clown)
    circus = models.ForeignKey(Circus)

and my admin:

class ClownInline(admin.TabularInline):
    model = WorkedAt
    fields = ['clown__name','clown__edit_link']


class CircusAdmin(admin.ModelAdmin):
    inlines = [
        ClownInline,
    ]
    exclude = ('clowns',)

However I get this error:

Unknown field(s) (clown__name) specified for WorkedAt

(I'm on Django 1.6)

Update: Why won't this work either. (Added calculated field to through model.)

class Clown(models.Model):
    name = models.CharField(max_length=255)
    def edit_link(self):
        return ...

class Circus(models.Model):
    clowns = models.ManyToManyField(Clown, blank=True, through='WorkedAt')
    name = models.CharField(max_length=255)

class WorkedAt(models.Model):
    clown = models.ForeignKey(Clown)
    circus = models.ForeignKey(Circus)
    @property
    def edit_link(self):
        return self.clown.edit_link()

and my admin:

class ClownInline(admin.TabularInline):
    model = WorkedAt
    fields = ['edit_link']


class CircusAdmin(admin.ModelAdmin):
    inlines = [
        ClownInline,
    ]
    exclude = ('clowns',)
merwok
  • 6,779
  • 1
  • 28
  • 42
Greg
  • 45,306
  • 89
  • 231
  • 297
  • The `fields` have to be a database field from the `WorkedAt` model. It cannot be a field of underlying model. In this case, you can have the inline as `Clown` on the `Circus` model, and do away with `WorkedAd` altogether – karthikr Feb 04 '14 at 20:37
  • Ok, check out my update. If I added a method right to the through model why won't even that show up? – Greg Feb 04 '14 at 20:50
  • Can you post a stack trace? – sj7 Feb 08 '14 at 09:34
  • Defining both `fields` and `readonly_fields` should make this work. – merwok Jun 20 '17 at 17:59

2 Answers2

6

Try this. Hope it solves your problem

class ClownInline(admin.TabularInline):
    model = WorkedAt
    fields = ['clown_name', 'clown_edit_link']
    readonly_fields = ['clown_name', 'clown_edit_link']

    def clown_name(self, instance):
        return instance.clown.name
    clown_name.short_description = 'clow name'

    def clown_edit_link(self, instance):
        url = reverse("admin:%s_%s_change" % (instance.clown._meta.app_label, instance.clown._meta.module_name), args=(instance.clown.pk,))
        return '<a href="%s">%s</a>' % (url, instance.clown.name)
    clown_edit_link.allow_tags = True


class CircusAdmin(admin.ModelAdmin):
    inlines = [
        ClownInline,
    ]
    exclude = ('clowns',)
merwok
  • 6,779
  • 1
  • 28
  • 42
sj7
  • 1,291
  • 1
  • 12
  • 26
  • Big thanks for the attempt! For some reason it's still not working. I even had the your method ClownInline.clown_name return a simple string 'test' to rule out any issues, but it still can't find field clown_name. – Greg Feb 07 '14 at 13:44
2

I don't know if anyone still needs this, because this question is 4 years old but this solved my problem for in Django 2.0.3:

# models.py
class Clown(models.Model):
    name = models.CharField(max_length=255)
    def edit_link(self):
        return ...


class Circus(models.Model):
    clowns = models.ManyToManyField(Clown, blank=True, through='WorkedAt')
    name = models.CharField(max_length=255)


class WorkedAt(models.Model):
    clown = models.ForeignKey(Clown)
    circus = models.ForeignKey(Circus)


# admin.py
class WorkedAtInline(admin.TabularInline):
    model = WorkedAt
    extra = 1


class WorkedAtAdmin(admin.ModelAdmin):
    inlines = (WorkedAtInline,)


admin.site.register(Clown, WorkedAtAdmin)

Hope this helps anyone that stumbles upon this problem and looks into this answer.

King Reload
  • 2,780
  • 1
  • 17
  • 42