Rick Teller
Rick Teller

Reputation: 11

Django - how to display related many-to-many field in choice field?

I’m building a web app using Django for my music collection. For each album, there are multiple songs, and each song has one or more composers. Here’s the song model:

class Song(models.Model):
    title = models.CharField(max_length=50)
    composer = models.ManyToManyField(Artist)

    class Meta:
        ordering = ['title']
    
    def __str__ (self):
        return self.title

The Artist model contains firstname and lastname fields.

There are a number of occurrences of songs with the same title, and the only way to distinguish between them is by the composer. Currently, when songs are loaded into a choice field, only the title appears, using __str__() method. I’ve tried to include the composers, but haven’t found a way to make it work. Any suggestions?

Upvotes: 1

Views: 113

Answers (1)

Peter Krause
Peter Krause

Reputation: 49

You'll need to somehow insert the composers' names into the Song's __str__ method.

One way to do this is by fetching the first and last names of the composers and formatting them before displaying in the __str__. Take the following example:

def __str__(self):
   raw_composers = self.composers.values_list("first_name", "last_name")
   stringified_composers = [f"{first_name} {last_name}" for (first_name, last_name) in raw_composers]
   formatted_composers = ", ".join(stringified_composers)
   return f"{self.title} ({formatted_composers})"

While this does work, the Django admin pages that display these choices will be doing lots of queries (namely, N queries for each Song of the list, where N is the amount of Artists related to this song). Be sure to run a .prefetch_related(...) to speed things up a little!

Upvotes: 1

Related Questions