Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Django no longer supports ManyToMany fields in Admin list_display #22545

Open
AndrewSRea opened this issue Nov 25, 2022 · 2 comments
Open

Django no longer supports ManyToMany fields in Admin list_display #22545

AndrewSRea opened this issue Nov 25, 2022 · 2 comments
Labels
Content:Learn:Django Learning area Django docs

Comments

@AndrewSRea
Copy link

AndrewSRea commented Nov 25, 2022

MDN URL

https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Admin_site

What specific section or headline is this issue about?

Admin site / Configure list views

What information was incorrect, unhelpful, or incomplete?

Per Django, simply defining a genre field for the list_display because it is a ManyToManyField is no longer supported.
The genre field must be given a custom method, and then that method’s name must be added to list_display.
If the string given is a method of the model (Genre), ModelAdmin, or a callable, Django will HTML-escape the output by default. To escape user input and allow your own unescaped tags, use format_html().

What did you expect to see?

Creating the definition of display_genre:

def display_genre(self):
    """Create a string for the Genre. This is required to display genre in Admin."""
    return ', '.join(genre.name for genre in self.genre.all()[:3])

display_genre.short_description = 'Genre'

...creates an error when clicking the "Books" list in the Site Administration:

TypeError at /admin/catalog/book ... display_genre() takes 1 positional argument but 2 were given

I expect to see a column for "Genre" in the "Select book to change" admin menu.

Do you have any supporting links, references, or citations?

https://docs.djangoproject.com/en/4.0/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_display

Scroll down to the text: "A few special cases to note about list_display:"

Do you have anything more you want to share?

No response

MDN metadata

Page report details
@github-actions github-actions bot added Content:Learn:Django Learning area Django docs needs triage Triage needed by staff and/or partners. Automatically applied when an issue is opened. labels Nov 25, 2022
@sideshowbarker sideshowbarker added help wanted If you know something about this topic, we would love your help! and removed needs triage Triage needed by staff and/or partners. Automatically applied when an issue is opened. labels Nov 27, 2022
@hamishwillee
Copy link
Collaborator

Hi @AndrewSRea

I can't reproduce this. If I run the code from this repo - which matches what is indicated in https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Admin_site#configure_list_views the genre is displayed properly.

image

I have tried this on Windows on the Django 4.1.3 latest and also 4.0.2 (as per requirements.txt).

Given that it is trying to pass you two objects and the method takes only one, it is possibly you are declaring the display_genre as part of the BookAdmin rather than the Book model - so in the list of list_display options you're pointing to the case "A string representing a ModelAdmin method that accepts one argument, the model instance." - as this takes self and obj.

Note that I can change the original ...

class Book(models.Model):
    """Model representing a book (but not a specific copy of a book)."""
    ...

    def display_genre(self):
        """Creates a string for the Genre. This is required to display genre in Admin."""
        return ', '.join([genre.name for genre in self.genre.all()[:3]])

    display_genre.short_description = 'Genre'

To add import of admin and use the @admin.display to set the Genre heading:

from django.contrib import admin

class Book(models.Model):
    """Model representing a book (but not a specific copy of a book)."""
    ...

    @admin.display(description='Genre')
    def display_genre(self):
        """Creates a string for the Genre. This is required to display genre in Admin."""
        return ', '.join([genre.name for genre in self.genre.all()[:3]])

    #display_genre.short_description = 'Genre'

I could also move the method entirely to the BookAdmin. I am not sure what the right approach is - they are all valid options. I am tempted to perhaps make the change indicated here though, because using @admin.display(description='Genre') seems to be the way of setting the display now.

Thoughts?

@hamishwillee
Copy link
Collaborator

Django no longer supports ManyToMany fields in Admin list_display

PS that title is a bit confusing - it never has, and the text specifically makes that clear. So the only thing that has changed since this was written is that decorators an be used to set the display heading.

@hamishwillee hamishwillee removed the help wanted If you know something about this topic, we would love your help! label Jan 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Content:Learn:Django Learning area Django docs
Projects
None yet
Development

No branches or pull requests

3 participants