Django admin.py fieldsets: How to add a field from a ManyToMany field inside listdisplay?

Viewed 24

I have these 2 models:

class Size(models.Model):
    _id = models.AutoField(primary_key=True, editable=False)
    size = models.CharField(max_length=50, null=True, blank=False)

    SIZE_TYPES = (
      ('XS', 'XS'),
      ('S', 'S'),
      ('M', 'M'),
      ('L', 'L'),
      ('XL', 'XL'),
      ('XXL', 'XXL'),
    )
    size_type           = models.CharField(max_length=10, choices=SIZE_TYPES, null=True, blank=True)

    GENDERS = (
    ('M', 'Male'),
    ('F', 'Female'),
    ('U', 'Unisex'),
)
    gender = models.CharField(max_length=50, choices=GENDERS, null=True, blank=False)


    def __str__(self) -> str:
        return f'{self.size} ({self.size_type}) - {self.gender}'

and:

class Product(models.Model):
    _id = models.AutoField(primary_key=True, editable=False) 
    user = models.ForeignKey(CustomUser, on_delete=models.SET_NULL, null=True) 
    category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True)
    brand = models.ForeignKey(Brand, on_delete=models.SET_NULL, null=True) 
    size = models.ManyToManyField(Size)
    (... other attributes)

and on my admin.py I want that ProductAdmin had the Size's attributes on listdisplay, but it doesn't work

so I have my ProductAdmin like this:

@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):

list_display = ['_id','name', 'brand', 'price', 'stock', 'category','rating','user','size']

But I can't get it to work, I've tried also size__size, also doesn't work.

What I need:

  • For list_display, I just want that the admin could see the product's size as a column on the Product's table in admin panel.

The Product table should look like this:

id name (...) size
1 Jordan sneakers (...) 7.5 (US) - M
1 Answers

I believe you would have to add a Custom Admin Column. It does make sense because Django doesn't know how to represent the Many-To-Many by itself

size_string
@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
    list_display = ['_id','name', 'brand', 'price', 'stock', 'category','rating','user','size_string']

    def size_string(self, obj):
        s = ''
        for i in obj.size.all():
            s += i.size +', '
        return s

Note: you might be able to call the function + column size instead of size_string ..I'm not sure, I always named it different.

Related