django admin inline many to many custom fields

maazza picture maazza · Nov 6, 2013 · Viewed 16.5k times · Source

Hi I am trying to customize my inlines in django admin.

Here are my models:

class Row(models.Model):
    name = models.CharField(max_length=255)

class Table(models.Model):
    rows = models.ManyToManyField(Row, blank=True)
    name = models.CharField(max_length=255)

    def __unicode__(self):
        return self.name

and my admin:

class RowInline(admin.TabularInline):
    model = Table.rows.through
    fields = ['name']


class TableAdmin(admin.ModelAdmin):
    inlines = [
        RowInline,
    ]
    exclude = ('rows',)

However I get this error

ImproperlyConfigured at /admin/table_app/table/1/

'RowInline.fields' refers to field 'name' that is missing from the form.

How is that possible ?

Answer

sj7 picture sj7 · Feb 5, 2014
class RowInline(admin.TabularInline):
    model = Table.rows.through
    fields = ['name']

This presents a problem because Table.rows.through represents an intermediate model. If you would like to understand this better have a look at your database. You'll see an intermediate table which references this model. It is probably named something like apname_table_rows. This intermeditate model does not contain the field, name. It just has two foreign key fields: table and row. (And it has an id field.)

If you need the name it can be referenced as a readonly field through the rows relation.

class RowInline(admin.TabularInline):
    model = Table.rows.through
    fields = ['row_name']
    readonly_fields = ['row_name']

    def row_name(self, instance):
        return instance.row.name
    row_name.short_description = 'row name'


class TableAdmin(admin.ModelAdmin):
    inlines = [
        RowInline,
    ]
    exclude = ('rows',)