pythondjangodjango-formsdjango-admindjango-modeladmin

How To Edit ManyToManyField In Django Admin list Display Page?


I want to add Many2Many fields editable in Django admin list_display page. The model structure as below,

class Genre(models.Model):
    name = models.CharField(max_length=250, unique=True)


class Movie(models.Model):
    name = models.CharField(max_length=250)
    genre = models.ManyToManyField(Genre)

And I tried as,

class MovieAdmin(admin.ModelAdmin):
    list_display = ['name', 'genre']
    list_editable = ['genre']

Above throws an error.


Solution

  • Django by default won't allow to add ManyToManyField in list_editable in ModelAdmin. So we need to override model admin methods.

    On looking your models you need to follow below steps to get the ManyToManyField editable in list display page.

    In apps/forms.py you need to define which ManyToMany fields you need to make editable in list display page. As below,

    from django import forms
    from app.models import Genre
    
    
    class MovieChangeListForm(forms.ModelForm):
    
        # here we only need to define the field we want to be editable
        genre = forms.ModelMultipleChoiceField(queryset=Genre.objects.all(), 
            required=False)
    

    In app/admin.py you need to override methods of model admin. As below,

    from django.contrib import admin
    from django.contrib.admin.views.main import ChangeList
    from app.models import Movie
    from app.forms import MovieChangeListForm
    
    class MovieChangeList(ChangeList):
    
        def __init__(self, request, model, list_display,
            list_display_links, list_filter, date_hierarchy,
            search_fields, list_select_related, list_per_page,
            list_max_show_all, list_editable, model_admin):
    
            super(MovieChangeList, self).__init__(request, model,
                list_display, list_display_links, list_filter,
                date_hierarchy, search_fields, list_select_related,
                list_per_page, list_max_show_all, list_editable, 
                model_admin)
    
            # these need to be defined here, and not in MovieAdmin
            self.list_display = ['action_checkbox', 'name', 'genre']
            self.list_display_links = ['name']
            self.list_editable = ['genre']
    
    
    class MovieAdmin(admin.ModelAdmin):
    
        def get_changelist(self, request, **kwargs):
            return MovieChangeList
    
        def get_changelist_form(self, request, **kwargs):
            return MovieChangeListForm
    
    
    admin.site.register(Movie, MovieAdmin)
    

    Now you all set to check the changes, run server and check django admin for Movie model. You can edit ManyToMany field directly from list display page.

    Note : If you are going to use muliptle ManyToManyFields editable in list then, you need to set DATA_UPLOAD_MAX_NUMBER_FIELDS in settings.py .