django保存外键对象列表到m2m字段w /通过模型订购

时间:2016-05-09 02:24:27

标签: django model manytomanyfield

我有一个带有javascript的html表,它允许对通过POST上的表单传递track_id列表和行顺序列表的行进行排序。

我刚刚为模型添加了类PlaylistTrack,因此我可以在tracks.m2m字段中添加排序。在我添加直通模型之前,我在下面的视图工作,但现在我不知道如何保存轨道的列表与其相关的订单号,因为我无法使用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")

2 个答案:

答案 0 :(得分:1)

您需要获取将要添加的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")

答案 1 :(得分:1)

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是轨道数)。