Nathan Osman
Nathan Osman

Reputation: 73295

How to customize the label displayed for a ManyToManyField in an inline model admin?

Let's suppose I have the following model definition:

class Topping(models.Model):
    name = models.CharField(max_length=40)

class Pizza(models.Model):
    toppings = models.ManyToManyField(Topping)

Now let's suppose I want to register the models with the admin site, using an inline model admin to allow toppings to be added while editing pizzas:

@admin.register(Topping)
class ToppingAdmin(admin.ModelAdmin):
    pass

class ToppingInline(admin.TabularInline):
    model = Pizza.toppings.through
    verbose_name = 'topping'
    verbose_name_plural = 'toppings'

@admin.register(Pizza)
class PizzaAdmin(admin.ModelAdmin):
    exclude = ('toppings',)
    inlines = (ToppingInline,)

This leads to a rather glaring issue:

enter image description here

As you can see, the label is ugly. Is there a way to customize it?

Upvotes: 4

Views: 309

Answers (2)

Derek Kwok
Derek Kwok

Reputation: 13078

An quicker and dirtier alternative to defining a model class for the relationship is to redefine the __str__ or __unicode__ method:

class ToppingInline(admin.TabularInline):
    ...
    Pizza.toppings.through.__str__ = lambda self: 'Topping'

Upvotes: 3

quaspas
quaspas

Reputation: 1351

You would control what displays for an object using the __str__ or __unicode__ method.

You could manage the many to many yourself to define this attribute like this:

...

class Pizza(models.Model):
    toppings = models.ManyToManyField(Topping, through="PizzaToppingRelationship")


class PizzaToppingRelationship(models.Model):
    pizza = models.ForeignKey(Pizza)
    topping = models.ForeignKey(Topping)

    def __str__(self):
        return 'Pizza Topping - {}'.format(self.topping.name)

Upvotes: 2

Related Questions