5

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.

andyw
  • 3,505
  • 2
  • 30
  • 44
  • 1
    Can you *post the error*? – Willem Van Onsem Jul 13 '18 at 12:45
  • 1
    I got error like "The value of 'list_display[1]' must not be a ManyToManyField" – Amal chempazhanthy Jul 13 '18 at 12:54
  • 1
    try to create `through` model [https://docs.djangoproject.com/en/2.0/topics/db/models/#extra-fields-on-many-to-many-relationships](https://docs.djangoproject.com/en/2.0/topics/db/models/#extra-fields-on-many-to-many-relationships)(like MovieGenreLink, then create inline form in your admin where `formset = inlineformset_factory(Movie, Movie.genre.through, fields=(genre,))`. And after this add this inline form in your Movie Admin using `inlines = [MovieGenreLinkInline]`. – Max Jul 13 '18 at 13:10
  • Possible duplicate of [Django admin: ManyToManyField in list\_editable?](https://stackoverflow.com/questions/15655587/django-admin-manytomanyfield-in-list-editable) – Junaid Apr 25 '19 at 17:20

2 Answers2

3

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 .

  • 1
    For me, I had to add an extra field to the init of method of `ChangeList` – Junaid Apr 25 '19 at 16:57
  • 1
    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, sortable_by): super(ItemChangeList, 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, sortable_by) – Junaid Apr 25 '19 at 16:59
  • Works great on Django2, but on Django3 it shows empty form, where can be problem? – Ramaz Kadgaev Jul 22 '21 at 11:20
  • in Django3 2023 it requires yet another argument. Does anyone have any idea what that is? – yaozhang Mar 30 '23 at 23:12
0

As far as I understand, you want to add the model in your admin page.

to do so, you need to simply do this in your admin.py file inside your django app

admin.site.register(MovieAdmin)

It is automatically editable. Hope this helps.

DeprecatedAPI
  • 125
  • 1
  • 11