django 将外键对象列表保存到 m2m 字段,通过模型排序

django saving list of foreignkey objects to m2m field w/ through model with ordering

我有一个 html table w/ javascript 允许通过 [=30] 上的表单对传递 track_id 列表和行顺序列表的行进行排序=].

我刚刚为模型添加了 class PlaylistTrack using through ,这样我就可以向 tracks.m2m 字段添加排序。在我添加直通模型之前,我在下面看到的视图有效,但现在我不确定我应该如何保存带有相关订单号的 list 曲目,因为我无法使用 add () 并且我必须使用 create()。我应该如何在我的视图中使用 create() 来保存 track_id 的列表并将订单号与列表相关联?我可以使用 bulk_create 吗?

models.py:

class Playlist(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, default=1)
    name = models.CharField(max_length=50)
    tracks = models.ManyToManyField(Track, through='PlaylistTrack')

    def __str__(self):
        return self.name

class PlaylistTrack(models.Model):
    track = models.ForeignKey(Track)
    playlist = models.ForeignKey(Playlist)
    order = models.PositiveIntegerField()

    class Meta:
        ordering = ['order']

views.py:

def add_track(request):
    active_playlist = Playlist.objects.get(id=request.POST.get('playlist_id'))
    add_tracks = request.POST.getlist('track_id')
    if request.POST.get('playlist_id'):
        active_playlist.tracks.add(*add_tracks) # how to use create or bulk_create?
    return redirect("playlists:list_playlists")

您需要获取 Track 个将被添加的对象:

Track.objects.filter(pk__in=add_tracks)

--

由于 order 字段必须填写,您不能在 M2M 字段上使用 .add()。你必须自己创建对象:

def add_track(request):
    playlist = Playlist.objects.get(id=request.POST.get('playlist_id'))
    for i, track_id in enumerate(request.POST.getlist('track_id'), start=1):
        track = Track.objects.get(pk=track_id)
        PlaylistTrack.objects.create(track=track, playlist=playlist, order=i)
    return redirect("playlists:list_playlists")

Ozgur 的回答已经基本涵盖了您。但是,您不需要从数据库中获取 PlaylistTrack 实例,您可以使用 bulk_create:

def add_track(request):
    playlist_id = request.POST.get('playlist_id')
    track_ids = enumerate(request.POST.getlist('track_id'), start=1)
    PlaylistTrack.objects.bulk_create([
        PlaylistTrack(playlist_id=playlist_id, track_id=track_id, order=i) 
            for i, track_id in track_ids
    ])
    return redirect("playlists:list_playlists")

这将整个过程减少到单个数据库操作,您之前有 (1 + 2n) 个操作(n 是轨道数)。