Django admin page autocomplete on reverse ForeignKey

2.4k Views Asked by At

Disclamer: This is an edit question because I got some answers until now.

I would like to create an autocomplete field in InlineModelAdmin, with similar behavior as autocomplete_fields. I know, Django natively supports this only on ForeignKey, but I need it on the reverse side.

Is there a way - or a library that could do this?

I look into :

https://django-autocomplete-light.readthedocs.io/en/master/tutorial.html

https://django-grappelli.readthedocs.io/en/latest/customization.html

https://django-admin-autocomplete-all.readthedocs.io/en/latest/readme.html

But I didn't found this functionality...

Past question code:


I have models like this:

Models

class Customer(models.Model):

    customer_ref = models.CharField(unique=True, max_length=50)
    name = models.CharField(null=False, max_length=80)
    country = models.CharField(null=True, max_length=50)



class Assortment(models.Model):

    name = models.CharField(null=False, max_length=50)
    customers = models.ManyToManyField(Customer, related_name='assortments', blank=True)
    products = models.ManyToManyField(Product, related_name='assortments', blank=True)


class Subsidiary(models.Model):

    subsidiary_ref = models.CharField(unique=True, max_length=50)
    name = models.CharField(null=False, max_length=80)
    address = models.TextField(null=True)
    city = models.CharField(null=True, max_length=50)
    coordinates_x = models.DecimalField(null=True, decimal_places=2, max_digits=6)
    coordinates_y = models.DecimalField(null=True, decimal_places=2, max_digits=6)
    phone_number = models.CharField(null=True, max_length=50)
    frequency = models.ForeignKey(Frequency, on_delete=models.SET_NULL, null=True)
    channel = models.CharField(null=True, blank=True, max_length=50)
    subchannel = models.CharField(null=True, blank=True, max_length=50)

    user = models.ForeignKey(User, related_name='subsidiaries', on_delete=models.SET_NULL, null=True)
    day_planned = models.BooleanField(default=False)

    customer = models.ForeignKey(Customer, on_delete=models.CASCADE, related_name='subsidiaries')





class Asset(models.Model):

    identification = models.CharField(unique=True, max_length=50)
    serial = models.CharField(max_length=50)
    name = models.CharField(null=True, max_length=50)

    subsidiary = models.ForeignKey(Subsidiary, related_name='assets', null=True, blank=True, on_delete=models.DO_NOTHING)

Admin

@admin.register(Customer)
class CustomerAdmin(admin.ModelAdmin):
    list_display = ['customer_ref', 'name', 'country']
    list_filter = ['country']
    autocomplete_fields = ['assortments']


@admin.register(Subsidiary)
class SubsidiaryAdmin(admin.ModelAdmin):
    exclude = ['day_planned']
    list_display = ['subsidiary_ref', 'customer', 'name', 'address', 'phone_number', 'frequency', 'user']
    list_editable = ['frequency', 'user']
    list_filter = ['frequency', 'user']
    search_fields = ['subsidiary_ref', 'customer__name', 'name']
    autocomplete_fields = ['assets']

CustomerAdmin is 'working' without error but field 'assortments' is not visible.

SubsidiaryAdmin throws error :

<class 'mobileapp.admin.SubsidiaryAdmin'>: (admin.E038) The value of 'autocomplete_fields[0]' must be a foreign key or a many-to-many field.

witch is weird because I don't see any difference from the first example.

How to fix this?

1

There are 1 best solutions below

0
On

assortments is not visible in the list page as you have set list_display to

list_display = ['customer_ref', 'name', 'country']

Since assortments is a many-to-many relationship, you have to write a custom ModelAdmin to display them.

As mentioned in the django docs, autocomplete_fields works only for FK & M2M fields of that model. In the AssetAdmin, you can set autocomplete for Subsidiary field.

@admin.register(Asset)
class AssetAdmin(admin.ModelAdmin):
    autocomplete_fields = ['subsidiary']