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 的回答已经基本涵盖了您。但是,您不需要从数据库中获取 Playlist
或 Track
实例,您可以使用 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
是轨道数)。
我有一个 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 的回答已经基本涵盖了您。但是,您不需要从数据库中获取 Playlist
或 Track
实例,您可以使用 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
是轨道数)。