Django - 如何通过多个字段 sort/order 多个对象?

Django - how to sort/order multiple objects by multiple fields?

我想在我的网站上展示一张音乐专辑,问题是专辑本身有两张光盘,每张光盘有 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')

这将按光盘编号对专辑中的所有曲目进行排序,然后按这些光盘中的曲目排序。

编辑:

要通过光盘显示它们,您可以这样做:

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 %}