Django - как отсортировать/упорядочить несколько объектов по нескольким полям?

Я хочу отобразить музыкальный альбом на своем сайте, проблема в том, что сам альбом состоит из двух дисков, и каждый диск содержит x треков. Теперь мне интересно, как я могу отобразить это разделение на моем шаблоне Django, поскольку я хочу, чтобы это выглядело так:

Disc 1
   - Title - 1
   - Title - 2
   - Title - 3
   - Title - 4
   ...
Disc 2
   - Title - 1
   - Title - 2
   - Title - 3
   - Title - 4
   ...

Это мой взгляд:

def music_album_detail(request, pk):
    music_album = get_object_or_404(MusicAlbums, pk=pk)
    music_album_tracks = MusicTracks.objects.filter(album=music_album).order_by('track')
    args = {
        'music_album': music_album,
        'music_album_tracks': music_album_tracks,
    }
    return render(request, 'App/music_album_detail.html', args)

В настоящее время в моем шаблоне я делаю только следующее:

{% for music_album_track in music_album_tracks %}
  <td>{{ music_album_track.track }}</td>
  ...

Вот как выглядит моя модель:

class MusicAlbums(models.Model):
    objects = RandomManager()
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    title = models.TextField(verbose_name=_("Title"), blank=False, null=True, editable=False, max_length=255)
    artist = models.ForeignKey(MusicArtists, on_delete=models.CASCADE, related_name='album_artist')
    cover = models.ImageField(verbose_name=_("Cover"), blank=True, null=True, upload_to=get_file_path_images)
    cover_tn = models.ImageField(verbose_name=_("Cover Thumbnail"), blank=True, null=True, upload_to=get_file_path_images)
    release_date = models.DateField(verbose_name=_("Release Date"), blank=True, null=True, editable=False)
    genre_relation = models.ManyToManyField(through='GenreMusicAlbum', to='Genre')
    total_discs = models.IntegerField(verbose_name=_("Total Discs #"), blank=True, null=True,)
    total_tracks = models.IntegerField(verbose_name=_("Total Tracks #"), blank=True, null=True,)
    copyright = models.TextField(verbose_name=_("Copyright"), blank=True, null=True, editable=False, max_length=255)
    date_added = models.DateTimeField(auto_now_add=True, blank=True, verbose_name=_("Date Added"))


class MusicTracks(models.Model):
    objects = RandomManager()
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    file = models.ForeignKey(Files, on_delete=models.CASCADE, related_name='track_file')
    bitrate = models.IntegerField(verbose_name=_("Bitrate (bps)"), blank=True, null=True, editable=False)
    duration = models.FloatField(verbose_name=_("Duration"), blank=True, null=True, editable=False, max_length=255)
    size = models.BigIntegerField(blank=True, null=True, verbose_name=_("Size (byte)"))
    title = models.TextField(verbose_name=_("Title"), blank=True, null=True, max_length=255)
    artist = models.ForeignKey(MusicArtists, on_delete=models.CASCADE, related_name='track_artist')
    album = models.ForeignKey(MusicAlbums, on_delete=models.CASCADE, related_name='track_album')
    release_date = models.DateField(verbose_name=_("Release Date"), blank=True, null=True, editable=False)
    disc = models.IntegerField(verbose_name=_("Disc #"), blank=True, null=True,)
    track = models.IntegerField(verbose_name=_("Track #"), blank=True, null=True,)
    date_added = models.DateTimeField(auto_now_add=True, blank=True, verbose_name=_("Date Added"))

Есть идеи, как я могу установить такое изображение в моем шаблоне?

Добрые пожелания и благодарность заранее

Вы должны использовать диск в другой модели и установить FK для этого:

class MusicAlbums(models.Model):
    ...

class MusicDiscs(models.Model):
    album = models.ForeignKey(...)
    number = models.IntegerField(...) # For example 

class MusicTracks(models.Model):
    disc = models.ForeignKey(...)

Таким образом, каждый альбом имеет несколько дисков, и каждый диск имеет свои треки

Теперь вы можете получить диски в вашем представлении и передать их вместе с дорожками в шаблон:

def music_album_detail(request, pk):
    music_album_discs = Musicdiscs.objects.filter(...)

и в ваших шаблонах:

{% for music_disc in music_album_discs %}
  <td>{{ music_disc.number }}</td>
  {% for music_track in music_album_tracks %}
    <td>{{ music_track.track }}</td>

Вы можете упорядочить набор вопросов сначала по disc, а затем по track:

MusicTracks.objects.filter(album=music_album).order_by('disc', 'track')

Это упорядочит все треки в альбоме по номеру диска, а затем по трекам на этих дисках.

EDIT:

Чтобы отобразить их по дискам, вы можете сделать примерно следующее:

def music_album_detail(request, pk):
    music_album = get_object_or_404(MusicAlbums, pk=pk)
    music_album_tracks_by_disc = {}

    for track in MusicTracks.objects.filter(album=music_album).order_by('track'):
        if track.disk in music_album_tracks_by_disc:
            music_album_tracks_by_disc[track.disk].append(track)
        else:
            music_album_tracks_by_disc[track.disk] = [track]

    context = {
        'music_album': music_album,
        'music_album_tracks_by_disc': music_album_tracks_by_disc,
    }
    return render(request, 'App/music_album_detail.html', context=context)
{% for disc, tracks in music_album_tracks_by_disc.items %}
  <td>Disc {{ disc }}</td>
  {% for track in tracks %}
    <td>{{ track.track }}</td>
  {% endfor %}
{% endfor %}
Вернуться на верх